User Tools

Site Tools


blog:2025-07-03-002



2025-07-03 C: Convert between big-endian and little-endian values

  • // Specialization for 2-byte types.
    template<>
    inline void endian_byte_swapper< 2 >(char* dest, char const* src)
    {
        // Use bit manipulations instead of accessing individual bytes from memory, much faster.
        ushort* p_dest = reinterpret_cast< ushort* >(dest);
        ushort const* const p_src = reinterpret_cast< ushort const* >(src);
        *p_dest = (*p_src >> 8) | (*p_src << 8);
    }
    
    // Specialization for 4-byte types.
    template<>
    inline void endian_byte_swapper< 4 >(char* dest, char const* src)
    {
        // Use bit manipulations instead of accessing individual bytes from memory, much faster.
        uint* p_dest = reinterpret_cast< uint* >(dest);
        uint const* const p_src = reinterpret_cast< uint const* >(src);
        *p_dest = (*p_src >> 24) | ((*p_src & 0x00ff0000) >> 8) | ((*p_src & 0x0000ff00) << 8) | (*p_src << 24);
    }

通用模板

  • C++:
    template <typename T>
    void SwapEnd(T& var)
    {
        static_assert(std::is_pod<T>::value, "Type must be POD type for safety");
        std::array<char, sizeof(T)> varArray;
        std::memcpy(varArray.data(), &var, sizeof(T));
        for(int i = 0; i < static_cast<int>(sizeof(var)/2); i++)
            std::swap(varArray[sizeof(var) - 1 - i],varArray[i]);
        std::memcpy(&var, varArray.data(), sizeof(T));
    }
  • C:
    #include <stdio.h>
    #include <string.h>
    #include <stdbool.h>
    
    // 定義一個宏來檢查 POD 類型
    #define IS_POD_TYPE(type) (sizeof(type) == sizeof(type))
    
    void SwapEnd(void* var, size_t size) {
        // 檢查是否為 POD 類型
        if (!IS_POD_TYPE(*((char*)var))) {
            printf("Type must be POD type for safety\n");
            return;
        }
    
        // 創建一個字節數組來存儲變量
        char varArray[size];
        memcpy(varArray, var, size);
    
        // 交換字節
        for (size_t i = 0; i < size / 2; i++) {
            char temp = varArray[size - 1 - i];
            varArray[size - 1 - i] = varArray[i];
            varArray[i] = temp;
        }
    
        // 將結果複製回原變量
        memcpy(var, varArray, size);
    }
    
    // 測試函數
    int main() {
        int num = 0x12345678; // 測試數據
        printf("Original: 0x%X\n", num);
        SwapEnd(&num, sizeof(num));
        printf("Swapped: 0x%X\n", num);
        return 0;
    }

Linux

  • #include <iostream>
    
    #include <endian.h>
    
    template<size_t N> struct SizeT {};
    
    #define BYTESWAPS(bits) \
    template<class T> inline T htobe(T t, SizeT<bits / 8>) { return htobe ## bits(t); } \
    template<class T> inline T htole(T t, SizeT<bits / 8>) { return htole ## bits(t); } \
    template<class T> inline T betoh(T t, SizeT<bits / 8>) { return be ## bits ## toh(t); } \
    template<class T> inline T letoh(T t, SizeT<bits / 8>) { return le ## bits ## toh(t); }
    
    BYTESWAPS(16)
    BYTESWAPS(32)
    BYTESWAPS(64)
    
    #undef BYTESWAPS
    
    template<class T> inline T htobe(T t) { return htobe(t, SizeT<sizeof t>()); }
    template<class T> inline T htole(T t) { return htole(t, SizeT<sizeof t>()); }
    template<class T> inline T betoh(T t) { return betoh(t, SizeT<sizeof t>()); }
    template<class T> inline T letoh(T t) { return letoh(t, SizeT<sizeof t>()); }
    
    int main()
    {
        std::cout << std::hex;
        std::cout << htobe(static_cast<unsigned short>(0xfeca)) << '\n';
        std::cout << htobe(0xafbeadde) << '\n';
    
        // Use ULL suffix to specify integer constant as unsigned long long 
        std::cout << htobe(0xfecaefbeafdeedfeULL) << '\n';
    }
  • output:
    cafe
    deadbeaf
    feeddeafbeefcafe

Reference

TAGS

  • 1 person(s) visited this page until now.

blog/2025-07-03-002.txt · Last modified: 2025/07/03 17:28 by jethro