为什么 to_be_bytes() 和 to_le_bytes() 与我在这里期望的相反?

Why does to_be_bytes() and to_le_bytes() do the opposite of what I expect here?

也许问题应该是“为什么我期望 to_be_bytes() 和 to_le_bytes() 在这里做相反的事情?”,但无论如何,情况是这样的:

fn main() {
    let buf: [u8; 2048] // Buffer I use to receive UDP messages

    let (_, entry, _) = unsafe { buf[14..].align_to::<u16>() };
    // In memory entry looks like: 00 44 16 15   21 04 03 5a   03 67 03 6a   03 64 88 91

    let [first, second] = entry[0].to_be_bytes();
    
    assert_eq!(first, 0x44);
    assert_eq!(second, 0x00);
}

不应该相反吗? big endianness不是像在内存中保留顺序吗?

大端意味着高字节在前存储(或传输)在最低地址。 Intel处理器是little endian,意思是低字节存储在低地址。

每个都有一些优点,但通常首选大端,这就是为什么网络协议和可移植数据格式通常是大端。为了与旧版本兼容,英特尔保留了小端。一些 CPU 具有可以在两者之间切换的模式,但英特尔从未这样做过。

很难确切知道您的期望出了什么问题,但我会尽力解释这里发生的事情。

当您执行 buf.align_to() 时,没有进行任何转换,字节按原样重新解释。所以 entry[0] (假设它 对齐的)将在内存中存储为 00 44 。您的系统可能是小端架构,因此 entry[0]value17408.

fn main() {
    let buf = [0x00, 0x44];
    let result = u16::from_ne_bytes(buf); // also doesn't try to reinterpret bytes
    assert_eq!(result, 17408);
}

所以现在,entry[0] 是小端系统上的 u16,表示值 17408。要使用大端表示法获得相同的值,如 to_be_bytes() 所做的那样,它将交换字节。


考虑到您的网络通信用例,其中通常以大端顺序对值进行编码,您可能希望使用 entry[0].from_be() 来获取 68.[=22 的正确值=]