目录
什么是字节序
内存是按字节编址的,每个地址对应一个字节。但 uint32_t、float、double 这类类型有多个字节,CPU 必须决定:一个多字节数据的几个字节,按什么顺序放进连续的内存地址里。
这个顺序就是字节序(endianness)。它只对「大于一个字节」的数据有意义——char、uint8_t、UTF-8 文本、字节数组都不受它影响。
0x12345678 的两种排法
以 4 字节整数 0x12345678 为例,假设它从地址 0x1000 开始存放:
0x12345678 的两种内存布局,地址从左到右递增
- 大端序(big-endian):最高有效字节
0x12放在最低地址0x1000,内存里读出来是12 34 56 78,和书写顺序一致。 - 小端序(little-endian):最低有效字节
0x78放在最低地址0x1000,内存里读出来是78 56 34 12,和书写顺序相反。
所以「大端 / 小端」说的是字节的排列,不是位的排列;0x12345678 这个数值本身没有变,变的只是它在内存里的落地方式。
为什么会有两种字节序
这更多是历史与工程取舍,而不是谁更「正确」。
- 小端序把低位字节放在低地址,做多字节加法时可以从低地址开始逐字节进位;把一个 32 位值截断成 16 位时,低半部分所在地址不变。早期一些 CPU 这样实现更省事。
- 大端序让内存里的字节顺序和数值的书写顺序一致,看 hexdump 时更符合直觉,网络协议因此选了它。
至于「哪种更快」,在现代 CPU 上基本没有差别,不要把它当成选型依据。
怎么判断当前机器的字节序
最直接的办法:拿一个多字节整数,按字节去看它的内存。
#include <stdint.h>
#include <stdio.h>
int main(void) {
uint32_t value = 0x12345678;
unsigned char *bytes = (unsigned char *)&value;
for (int i = 0; i < 4; i++) {
printf("%02x ", bytes[i]);
}
putchar('\n');
puts(bytes[0] == 0x78 ? "little-endian" : "big-endian");
return 0;
}
把小端机器上会输出:
78 56 34 12
little-endian