我从套接字读取一系列字节,我需要将n个字节的每个段作为项目放在一个结构中。
use std::mem;
#[derive(Debug)]
struct Things {
x: u8,
y: u16,
}
fn main() {
let array = [22 as u8, 76 as u8, 34 as u8];
let foobar: Things;
unsafe {
foobar = mem::transmute::<[u8; 3], Things>(array);
}
println!("{:?}", foobar);
}
当foobar
为24位时,我收到的错误表明array
为32位。那不是foobar
是24位(8 + 16 = 24)吗?
答案 0 :(得分:13)
这里的问题是y
字段是16位对齐的。所以你的内存布局实际上是
x
padding
y
y
请注意,交换x
和y
的顺序并不会有帮助,因为Rust的结构内存布局实际上是未定义的(因此仍然是32位,但无缘无故,但简单的编译器)。如果您依赖它,您将得到未定义的行为。
Purpose of memory alignment解释了对齐的原因。
您可以通过向结构添加属性repr(packed)
来防止对齐发生,但是您将失去性能并且能够引用字段:
#[repr(packed)]
struct Things {
x: u8,
y: u16,
}
最好的方法是不要使用transmute
,而是手动提取值并希望优化器加快速度:
let foobar = Things {
x: array[0],
y: ((array[1] as u16) << 8) | (array[2] as u16),
};
像byteorder这样的包可以简化从字节中读取不同大小和字节序的过程。
答案 1 :(得分:0)
use std::mem;
fn main() {
let bytes = vec!(0u8, 1u8,2u8, 3, 4, 5, 6, 7, 8, 9, 0xffu8, );
let data_ptr: *const u64 = unsafe { mem::transmute(bytes[0..4].as_ptr()) };
let data: u64 = unsafe { *data_ptr };
println!("{:#x}", data);
}