u8 作为 i32 与 i32::from_be_bytes([u8;4])

u8 as i32 vs i32::from_be_bytes([u8;4])

总自行车脱落,但我想知道

的相对效率
let mut buf = [0u8];
input.read(&mut buf)?;
Ok(buf[0] as i32)

let mut buf = [0u8; 4];
input.read(&mut buf[3..4])?;
Ok(i32::from_be_bytes(buf))

即使出于审美原因,也很难在它们之间做出选择,因为孤立地我更喜欢第一组代码,但我有并行方法来读取遵循后一种模式的 16、24 和 32 位整数数据使其在上下文中更具吸引力。

假设您打算存储负值,您的代码将无法正确处理有符号整数。如果一个文件有一个 i8 和值 -1 (0xFF),你将把它读作一个 u8 和值 255 并转换为 i32,产生错误的值(参见 this playground)。如果您希望值正确返回,您需要执行符号扩展。

我建议使用 byteorder crate,它具有以字节序感知方式正确读取整数的方法。生成的代码看起来像

use byteorder::{LE, ReadBytesExt};

reader.read_i8()? as i32;
reader.read_i16::<BE>()? as i32;
reader.read_i24::<BE>()? as i32;
reader.read_i32::<BE>()?;

看起来第一个会更有效率一些。它使用 movzx 而不是 bswap

你可以在这里看到: https://rust.godbolt.org/z/WxW1bj4Eh

编译器很难将 bswap 转换为 movzx,因为它需要通过读取才能理解缓冲区的其余部分为 0。