大小端存储 (Endianness) 学习笔记
1. 什么是大小端?
在计算机系统中,多字节数据(如 int, float 等)在内存中占用的字节数超过 1 个。当我们将这些数据存储在连续的内存地址中时,就涉及到了字节序(Byte Order)的问题,即:高位字节和低位字节谁先存在低地址,谁后存在高地址。
- MSB (Most Significant Byte): 最高有效字节(数据的"高位")。
- LSB (Least Significant Byte): 最低有效字节(数据的"低位")。
例如,十六进制数 0x12345678:
0x12是 MSB (高位)0x78是 LSB (低位)
2. 大端模式 (Big-Endian)
定义 :数据的高位字节 存储在内存的低地址 中,而数据的低位字节 存储在内存的高地址中。
特点:
- 内存中的字节顺序与我们平时书写/阅读数字的顺序(从左到右)一致。
- 也就是"高位在前"。
示例 :
存储 0x12345678 (假设起始地址为 0x100)
| 内存地址 | 0x100 (低) | 0x101 | 0x102 | 0x103 (高) |
|---|---|---|---|---|
| 数据 | 0x12 | 0x34 | 0x56 | 0x78 |
应用场景:
- 网络字节序 (Network Byte Order) 标准(TCP/IP 协议栈)。
- 某些 RISC 架构处理器(如 SPARC, PowerPC 的早期版本)。
3. 小端模式 (Little-Endian)
定义 :数据的低位字节 存储在内存的低地址 中,而数据的高位字节 存储在内存的高地址中。
特点:
- 也就是"低位在前"。
- 这种存储方式在进行类型转换(如 int 转 short)或加法运算时,CPU 处理起来可能更方便(低位对齐)。
示例 :
存储 0x12345678 (假设起始地址为 0x100)
| 内存地址 | 0x100 (低) | 0x101 | 0x102 | 0x103 (高) |
|---|---|---|---|---|
| 数据 | 0x78 | 0x56 | 0x34 | 0x12 |
应用场景:
- 常见的主机字节序 (Host Byte Order)。
- x86 / x64 架构 (Intel, AMD)。
- ARM (默认通常是小端,但可配置)。
4. 如何判断当前机器的大小端?
我们可以利用 C 语言的 union 特性或指针强制转换来检测。
方法一:使用 Union
union 的成员共享同一块内存空间。
c
#include <stdio.h>
int check_endian() {
union {
int i;
char c;
} un;
un.i = 1; // 0x00000001
// 如果是小端,低位 0x01 存在低地址,c 读取低地址也是 1
// 如果是大端,高位 0x00 存在低地址,c 读取低地址则是 0
return un.c;
}
int main() {
if (check_endian() == 1) {
printf("当前机器是:小端模式 (Little-Endian)\n");
} else {
printf("当前机器是:大端模式 (Big-Endian)\n");
}
return 0;
}
方法二:使用指针转换
c
#include <stdio.h>
int main() {
int a = 1;
char *p = (char*)&a; // 获取 int 的低地址字节
if (*p == 1) {
printf("小端\n");
} else {
printf("大端\n");
}
return 0;
}
5. 网络字节序与主机字节序转换
由于不同的计算机可能采用不同的字节序,为了保证数据在网络传输中的正确性,TCP/IP 协议规定:网络传输使用大端模式 (Big-Endian)。
因此,在发送数据前,需要将主机字节序 转换为网络字节序 ;接收数据后,需要将网络字节序 转换为主机字节序。
常用函数 (在 <arpa/inet.h> 或 <winsock2.h> 中):
htons(): Host to Network Short (16位)htonl(): Host to Network Long (32位)ntohs(): Network to Host Short (16位)ntohl(): Network to Host Long (32位)
记忆口诀:
- h (Host) 代表主机
- n (Network) 代表网络
- s (Short) 代表 16 位
- l (Long) 代表 32 位
6. 总结
| 特性 | 大端模式 (Big-Endian) | 小端模式 (Little-Endian) |
|---|---|---|
| 存储方向 | 高位 -> 低地址 | 低位 -> 低地址 |
| 直观性 | 符合人类阅读习惯 | 不符合阅读习惯,但在逻辑电路处理上有优势 |
| 典型应用 | 网络协议、PowerPC | x86, ARM, Windows, Linux (大部分) |