大小端
大端序 vs 小端序
大小端描述的是:一个多字节数(如 32 位 int)在内存里哪个字节放最低地址。
| 大端序 Big-Endian | 小端序 Little-Endian | |
|---|---|---|
| 规则 | 高字节存低地址 | 低字节存低地址 |
| 直觉 | 「大」的在前面,符合人读数字习惯 | 「小」的在前面 |
以 uint32_t num = 0x12345678 存到地址 0x00 为例(从低地址到高地址):
小端: 0x78 0x56 0x34 0x12
大端: 0x12 0x34 0x56 0x78
谁用哪种
| 端序 | 谁在用 |
|---|---|
| 大端 | 网络协议(IP 地址、端口 = 网络字节序)、JPEG/PNG 等文件格式、部分通信协议 |
| 小端 | ARM(Cortex-M 默认小端)、x86/x64 |
所以写网络程序、解析协议包时,常要
htonl/ntohl(主机序 ↔ 网络序)转换。 ARM 理论上可配置大小端(Cortex-M 的 AIRCR 位),但实际几乎全用小端。
判断方法
两种写法同一原理:写一个已知值 0x12345678,读最低地址的那个字节,看是低字节 0x78(小端)还是高字节 0x12(大端)。
① 指针强转
uint32_t num = 0x12345678;
uint8_t *p = (uint8_t *)# // 强转成字节指针,逐个看字节
if (p[0] == 0x78) {
// 最低地址存的是最低字节 → 小端
} else { // p[0] == 0x12
// 大端
}② 联合体
union {
uint32_t num;
uint8_t bytes[4];
} u;
u.num = 0x12345678;
if (u.bytes[0] == 0x78) {
// 小端
} else { // u.bytes[0] == 0x12
// 大端
}联合体里
num和bytes[]共享同一块内存,所以bytes[0]就是num的最低地址字节,等价于指针强转。