C语言应用笔记:整数字节大小端翻转

C语言应用笔记:整数字节大小端翻转

编码文章call10242025-09-11 15:46:374A+A-

在C语言中,实现大小端(Endian)翻转可以通过位操作或内存操作完成。以下提供两种常用方法:

方法1:位运算(推荐)

通过移位和掩码操作直接交换字节位置:

// 16位翻转(安全版本)
#define SWAP_ENDIAN_16(val) ({    \
    uint16_t _val = (val);        \
    (((_val) >> 8) & 0x00FF) |    \
        (((_val) << 8) & 0xFF00); \
})
// 32位翻转(安全版本)
#define SWAP_ENDIAN_32(val) ({       \
    uint32_t _val = (val);           \
    ((_val & 0x000000FF) << 24) |    \
        ((_val & 0x0000FF00) << 8) | \
        ((_val & 0x00FF0000) >> 8) | \
        ((_val & 0xFF000000) >> 24); \
})
// 64位翻转(安全版本)
#define SWAP_ENDIAN_64(val) ({                   \
    uint64_t _val = (val);                       \
    ((_val & 0x00000000000000FFULL) << 56) |     \
        ((_val & 0x000000000000FF00ULL) << 40) | \
        ((_val & 0x0000000000FF0000ULL) << 24) | \
        ((_val & 0x00000000FF000000ULL) << 8) |  \
        ((_val & 0x000000FF00000000ULL) >> 8) |  \
        ((_val & 0x0000FF0000000000ULL) >> 24) | \
        ((_val & 0x00FF000000000000ULL) >> 40) | \
        ((_val & 0xFF00000000000000ULL) >> 56);  \
})

方法2:内存操作

通过字节指针直接交换内存中的字节顺序:

// 16位大小端翻转
uint16_t swap_endian16(uint16_t value) {
    uint8_t *bytes = (uint8_t *)&value;
    return ((uint16_t)bytes[0] << 8) |
           ((uint16_t)bytes[1] << 0);
}
// 32位大小端翻转
uint32_t swap_endian32(uint32_t value) {
    uint8_t *bytes = (uint8_t *)&value;
    return ((uint32_t)bytes[0] << 24) |
           ((uint32_t)bytes[1] << 16) |
           ((uint32_t)bytes[2] << 8) |
           ((uint32_t)bytes[3] << 0);
}
// 64位大小端翻转
uint64_t swap_endian64(uint64_t value) {
    uint8_t *bytes = (uint8_t *)&value;
    return ((uint64_t)bytes[0] << 56) |
           ((uint64_t)bytes[1] << 48) |
           ((uint64_t)bytes[2] << 40) |
           ((uint64_t)bytes[3] << 32) |
           ((uint64_t)bytes[4] << 24) |
           ((uint64_t)bytes[5] << 16) |
           ((uint64_t)bytes[6] << 8) |
           ((uint64_t)bytes[7] << 0);
}

使用示例

#include "main.h"

int main(void) {
#ifdef ENDIAN_DEFINE
    // 16位测试
    uint16_t a = 0x1234;
    printf("0x%04X -> 0x%04X\n", a, SWAP_ENDIAN_16(a));
    // 32位测试
    uint32_t b = 0x12345678;
    printf("0x%08X -> 0x%08X\n", b, SWAP_ENDIAN_32(b));
    // 64位测试
    uint64_t c = 0x0123456789ABCDEF;
    printf("0x%016llX -> 0x%016llX\n", c, SWAP_ENDIAN_64(c));
#else
    // 16位测试
    uint16_t a = 0x1234;
    printf("0x%04X -> 0x%04X\n", a, swap_endian16(a));
    // 32位测试
    uint32_t b = 0x12345678;
    printf("0x%08X -> 0x%08X\n", b, swap_endian32(b));
    // 64位测试
    uint64_t c = 0x0123456789ABCDEF;
    printf("0x%016llX -> 0x%016llX\n", c, swap_endian64(c));
#endif
    return 0;
}

输出结果

0x1234 -> 0x3412
0x12345678 -> 0x78563412
0x0123456789ABCDEF -> 0xEFCDAB8967452301

关键说明

  1. 原理:大小端翻转的本质是反转多字节数据在内存中的存储顺序(大端序高位在前,小端序低位在前)。
  2. 可移植性:上述代码不依赖主机字节序,可在任何平台使用。
  3. 效率:位运算通常比内存操作更快,编译器会优化为高效指令(如bswap)。
  4. 类型安全:使用stdint.h中的明确宽度类型(如uint32_t)避免平台差异。

注意:实际开发中可优先使用编译器内置函数(如GCC的__builtin_bswap32()),但上述手动实现更具通用性。

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4