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

问题描述

也许问题应该是“为什么我希望 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 不就是把顺序保存在内存中吗?

解决方法

Big endian 意味着高字节首先存储(或传输),意味着在最低地址。 Intel 处理器是小端的,这意味着低字节存储在低地址中。

每个都有一些优点,但通常首选大端,这就是网络协议和可移植数据格式通常是大端的原因。为了与旧版本兼容,英特尔仍然保持小端。一些 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 值。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...