大端序(Big-Endian)和小端序(Little-Endian)是两种不同的字节存储顺序,用于描述多字节数据(如 u32, f64)在计算机内存中的存储方式。
对于一个 16 进制数 0x12345678 (这是一个 4 字节整数):
- 高位字节 (MSB) 是
0x12 - 低位字节 (LSB) 是
0x78
1. 区别图解
假设内存地址从 0x100 开始增长:
大端序 (Big-Endian)
符合人类阅读习惯。高位字节在前,低位字节在后。
| 内存地址 | 0x100 | 0x101 | 0x102 | 0x103 |
|---|---|---|---|---|
| 数据 | 12 | 34 | 56 | 78 |
- 应用场景:网络传输标准(Network Byte Order)、Java 虚拟机、PowerPC 架构。
小端序 (Little-Endian)
符合计算机处理逻辑。低位字节在前,高位字节在后。
| 内存地址 | 0x100 | 0x101 | 0x102 | 0x103 |
|---|---|---|---|---|
| 数据 | 78 | 56 | 34 | 12 |
- 应用场景:x86/x64 架构(Intel/AMD CPU)、ARM(默认)。
2. 为什么小端序更符合计算机逻辑?
你原文提到“小端序更符合计算机的处理逻辑”,原因在于:
- 类型转换方便:强制类型转换(如将
u32截断为u16)时,CPU 只需要读取低地址的字节,不需要移动指针指向的地址。 - 运算便利:加法器通常从低位开始运算(进位向高位),小端序使得低位数据先被读入,符合运算流水线。
3. 在 Rust 中的处理
Rust 提供了非常明确的方法来处理字节序,避免了 C 语言中依赖平台特性的未定义行为。
fn main() {
let num: u32 = 0x12345678;
// 转换为大端序字节数组
let be_bytes = num.to_be_bytes();
println!("Big Endian: {:x?}", be_bytes); // [12, 34, 56, 78]
// 转换为小端序字节数组
let le_bytes = num.to_le_bytes();
println!("Little Endian: {:x?}", le_bytes); // [78, 56, 34, 12]
// 网络编程常用:从字节数组还原整数
let network_data = [0x12, 0x34, 0x56, 0x78];
let value = u32::from_be_bytes(network_data);
assert_eq!(value, 0x12345678);
}