大小端
大小端(Endianness)描述的是多字节数据在内存中的存储顺序。
一、什么是大端与小端
以 32 位整型数 0x12345678 为例(每个十六进制字符占 4 bit,两个字符一个字节):
-
大端(Big Endian):高位字节存放在低地址,低位字节存放在高地址
地址: 0x00 0x01 0x02 0x03 内容: 0x12 0x34 0x56 0x78 -
小端(Little Endian):低位字节存放在低地址,高位字节存放在高地址
地址: 0x00 0x01 0x02 0x03 内容: 0x78 0x56 0x34 0x12
二、什么时候区分大小端,什么时候不区分
需要区分大小端的场景
-
网络通信:
- 网络协议如 TCP/IP 采用 大端序(又称网络字节序),不同主机交换数据时若字节序不同,必须进行转换(如
htons、htonl)。
- 网络协议如 TCP/IP 采用 大端序(又称网络字节序),不同主机交换数据时若字节序不同,必须进行转换(如
-
跨平台文件存储:
- 比如 BMP、WAV、TIFF 等格式会规定字段字节序,加载文件时需按格式解析。
-
嵌入式开发 / 裸机通信:
- MCU、DSP、SoC 通常硬件架构不一致,需统一字节序通信。
-
二进制协议解析:
- 自定义通信协议、序列化格式(如 Protobuf)需明确字节序。
不区分大小端的场景
-
单机应用层开发:
- 对字节序不敏感,比如纯数学计算、用户界面。
-
文本数据处理:
- 文本(如 JSON、XML)按字符序列处理,不涉及多字节合成。
-
高层语言内建类型操作:
- 使用
int,float等类型而不做底层转换时。
- 使用
三、大小端的应用场景
小端应用(Little Endian)
- x86/x86_64 架构:几乎所有 PC 和服务器平台默认使用小端。
- ARM 架构(默认小端):但支持配置成大端(如网络处理器)。
- Linux、Windows 系统:普遍使用小端格式。
- LLVM/GCC 编译器:编译默认生成小端指令流。
大端应用(Big Endian)
- 网络协议:TCP/IP 协议族默认大端(即网络字节序)。
- 某些嵌入式设备:如部分 PowerPC 架构或旧 MIPS 平台。
- 标准二进制文件格式:如 Java class 文件、某些音频/图像格式。
四、如何判断机器是大端还是小端
C语言方法(通用)
#include <stdio.h>
int main() {
unsigned int x = 0x12345678;
char *p = (char*)&x;
if (*p == 0x78) {
printf("Little Endian\n");
} else if (*p == 0x12) {
printf("Big Endian\n");
} else {
printf("Unknown Endianness\n");
}
return 0;
}
使用联合体判断(更直观)
union {
int i;
char c;
} endian_test = {0x01000000};
#define IS_BIG_ENDIAN (endian_test.c == 1)
Python 方法
import sys
print(sys.byteorder) # 输出 'little' 或 'big'
GCC 内置宏
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
printf("Little Endian\n");
#else
printf("Big Endian\n");
#endif
大端和小端只是字节在内存中的排列方式,不影响数值本身的逻辑意义。
