字节序(Byte Order)是指在多字节数据类型(如整数和浮点数)在内存中存储时,字节的排列顺序。常见的字节序有大端序(Big Endian)和小端序(Little Endian)。
- 大端序(Big Endian):在内存中,数据的高字节存储在低地址,低字节存储在高地址。
- 小端序(Little Endian):在内存中,数据的低字节存储在低地址,高字节存储在高地址。
例如,对于一个四字节的整数值 0x12345678:
- 在大端序中,它会被存储为:12 34 56 78
- 在小端序中,它会被存储为:78 56 34 12
不同的计算机架构和处理器可能采用不同的字节序。例如,Intel 和 AMD 的 x86 架构通常使用小端序,而PowerPC 和 SPARC 等架构通常使用大端序。
#include <iostream> void test() { // 从左向右依次为高位字节->低位字节 unsigned int value = 0xaabbccdd; unsigned char* p = (unsigned char*)&value; // 从低地址到高地址以此访问每个字节 printf("address: %lld value: %x\n", (long long)(p + 0), *(p + 0)); printf("address: %lld value: %x\n", (long long)(p + 1), *(p + 1)); printf("address: %lld value: %x\n", (long long)(p + 2), *(p + 2)); printf("address: %lld value: %x\n", (long long)(p + 3), *(p + 3)); } int main() { test(); return 0; }
程序输出结果:
address: 194812049492 value: dd address: 194812049493 value: cc address: 194812049494 value: bb address: 194812049495 value: aa
从输出结果来看,低地址存储 value 低字节数据,高地址存储了 value 高字节数据,这就是小端模式。后面再操作字节的时,我们就知道我们是从低字节开始访问原数据。
在网络编程中,字节序的不同可能会导致数据传输和解析的问题。为了解决这个问题,我们统一使用大端序的字节序,在网络中传输数据。大端序也称作网络字节序(Network Byte Order),在 Windows 和 Linux 网络编程中,都提供了相应的 API 将对应多字节类型数据转换为网络字节序。
下面示例代码在 visuao studio 2022 中运行,右键项目属性->链接器–>输入->附加依赖项 Ws2_32.lib
#include <iostream> #include <WinSock2.h> template<class T> void print_byte_order(T value) { unsigned char* p = (unsigned char*)&value; for (int i = 0; i < sizeof(T); ++i) { // 从低地址到高地址以此访问每个字节 printf("address: %lld value: %x\n", (long long)(p + i), *(p + i)); } printf("\n"); } void test() { // 转换16位整数为网络字节序 unsigned short host_short_value = 0x1234; unsigned short net_short_value = htons(host_short_value); print_byte_order(net_short_value); // 转换32位整数为网络字节序 unsigned long host_long_value = 0x12345678; unsigned long net_long_value = htonl(host_long_value); print_byte_order(net_long_value); } int main() { test(); return 0; }
address: 886901503232 value: 12 address: 886901503233 value: 34 address: 886901503232 value: 12 address: 886901503233 value: 34 address: 886901503234 value: 56 address: 886901503235 value: 78
从输出结果可以看到,使用 htons、htonl 实现将小端模式转换为大端模式(网络字节序)。