大小端模式是计算机存储多字节数据时的两种不同字节序规则,主要区别在于高低位字节在内存中的存放顺序。
0、计算机地址的增长方向
当定义一个数组时,地址是从低地址开始向到高地址递增的。
uint8_t bytes[4];
bytes[0] 地址小于 bytes[1]
bytes[1] 地址小于 bytes[2]
bytes[2] 地址小于 bytes[3]
本地写个程序打印地址如下
uint8_t bytes[4]{0};
cout << "bytes[0]:" << (void*)&bytes[0]<< endl;
cout << "bytes[1]:" << (void*)&bytes[1] << endl;
cout << "bytes[2]:" << (void*)&bytes[2] << endl;
cout << "bytes[3]:" << (void*)&bytes[3] << endl;
程序输出结果:
bytes[0]:0000000C99B9FC54
bytes[1]:0000000C99B9FC55
bytes[2]:0000000C99B9FC56
bytes[3]:0000000C99B9FC57
uint8_t占1个字节。地址从[0]开始依次递增1。
此时一个占多字节的数,比如0x12345678在存储的时候就有两种选择
方式一从高位开始存储
// 方式一
bytes[0] = 0x12;
bytes[1] = 0x34;
bytes[2] = 0x56;
bytes[3] = 0x78;
方式二从低位开始存储
// 方式二
bytes[0] = 0x78;
bytes[1] = 0x56;
bytes[2] = 0x34;
bytes[3] = 0x12;
一、大端模式(Big-Endian)
高位字节存储在内存的低地址
低位字节存储在内存的高地址
如下采用方式一存储为大端模式。
// 示例:0x12345678 在内存中的存储(地址由低到高):
// 地址增长 → 0x12 | 0x34 | 0x56 | 0x78
uint8_t bytes[4];
bytes[0] = 0x12;
bytes[1] = 0x34;
bytes[2] = 0x56;
bytes[3] = 0x78;
大端模式就好比是现实世界里的书写习惯,一个数字,从左往右写先写的是高位,后写的是低位,最后的是个位最低。
二、小端模式(Little-Endian)
低位字节存储在内存的低地址
高位字节存储在内存的高地址
小端模式采用方式二
示例:0x12345678 在内存中的存储(地址由低到高):
地址增长 → 0x78 | 0x56 | 0x34 | 0x12
uint8_t bytes[4];
bytes[0] = 0x78;
bytes[1] = 0x56;
bytes[2] = 0x34;
bytes[3] = 0x12;
我们知道地址是一个4或8字节的数。地址是有大小高低之分。大端模式是先写高位,但是高位所在的地址是低位。所以就有了小端模式。
三、为什么要有大小端模式呢
硬件设计差异:不同处理器架构(如Intel x86用小端,PowerPC用大端)选择不同存储策略
数据解析效率:小端模式在数值运算时可直接读取低位字节,减少移位操作
四、怎么判断大小端模式
1、C语言判断方法
通过联合体直接访问内存字节
bool is_little_endian() {
union
{
uint16_t num; // 2字节整数
uint8_t bytes[2]; // 2字节数组 地址的低位bytes[0] 高位bytes[1]
} test = {0x1122}; // 整数的高位0x11, 低位0x22
// 通过判断22的位置,或者通过判断11的位置
return (test.bytes[0] == 0x22); // 首位是低位字节则为小端
}
五、应用场景
场景 | 大端优势 | 小端优势 |
---|---|---|
网络传输 | TCP/IP协议统一采用大端(网络字节序) | 需转换(如htonl() |
数值计算 | 高位对齐需额外处理 | 直接读取低位字节,计算效率更高 |
数据兼容性 | ARM、PowerPC等架构原生支持 | x86、RISC-V等架构原生支持 |
六、记忆方法
- 大端 → 高存低(高位存低地址)大小端模式
- 小端 → 低存低(低位存低地址)