详解大端序与小端序 (Big Endian vs Little Endian)

详解大端序与小端序的区别、内存布局及 Rust 中的处理方式。

大端序(Big-Endian)和小端序(Little-Endian)是两种不同的字节存储顺序,用于描述多字节数据(如 u32, f64)在计算机内存中的存储方式。

对于一个 16 进制数 0x12345678 (这是一个 4 字节整数):

  • 高位字节 (MSB)0x12
  • 低位字节 (LSB)0x78

1. 区别图解

假设内存地址从 0x100 开始增长:

大端序 (Big-Endian)

符合人类阅读习惯。高位字节在前,低位字节在后。

内存地址0x1000x1010x1020x103
数据12345678
  • 应用场景:网络传输标准(Network Byte Order)、Java 虚拟机、PowerPC 架构。

小端序 (Little-Endian)

符合计算机处理逻辑。低位字节在前,高位字节在后。

内存地址0x1000x1010x1020x103
数据78563412
  • 应用场景:x86/x64 架构(Intel/AMD CPU)、ARM(默认)。

2. 为什么小端序更符合计算机逻辑?

你原文提到“小端序更符合计算机的处理逻辑”,原因在于:

  1. 类型转换方便:强制类型转换(如将 u32 截断为 u16)时,CPU 只需要读取低地址的字节,不需要移动指针指向的地址。
  2. 运算便利:加法器通常从低位开始运算(进位向高位),小端序使得低位数据先被读入,符合运算流水线。

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);
}