我正在从套接字中读取一系列字节,我需要将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是32位,而array是24位。foobar不应该是24位(8 + 16 = 24)吗?
发布于 2016-03-17 13:21:57
这里的问题是y字段是16位对齐的.所以你的内存布局实际上是
x
padding
y
y请注意,交换x和y的顺序没有帮助,因为Rust的内存布局实际上是未定义的(因此,除了编译器中的简单性之外,仍然是32位)。如果您依赖它,您将得到未定义的行为。
内存对齐的目的解释了对齐的原因。
通过将属性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),
};像字节顺序这样的板条箱可以简化从字节读取不同大小和大小的数据的过程。
发布于 2022-04-12 22:33:25
二进制代码和serde可以简单地完成这个任务。
use bincode::{deserialize};
use serde::{Deserialize};
#[derive(Deserialize, Debug)]
struct Things {
x: u8,
y: u16,
}
fn main() {
let array = [22 as u8, 76 as u8, 34 as u8];
let foobar: Things = deserialize(&array).unwrap();
println!("{:?}", foobar);
}这对于将结构序列化为字节也很有效。
use bincode::{serialize};
use serde::{Serialize};
#[derive(Serialize, Debug)]
struct Things {
x: u8,
y: u16,
}
fn main() {
let things = Things{
x: 22,
y: 8780,
};
let baz = serialize(&things).unwrap();
println!("{:?}", baz);
}发布于 2022-03-16 13:39:19
在处理具有char数组的结构时,我在使用byteorder机箱时遇到了问题。我无法通过编译器错误。最后我的演员是这样的:
#[repr(packed)]
struct Things {
x: u8,
y: u16,
}
fn main() {
let data: [u8; 3] = [0x22, 0x76, 0x34];
unsafe {
let things_p: *const Things = data.as_ptr() as *const Things;
let things: &Things = &*things_p;
println!("{:x} {:x}", things.x, things.y);
}
}请注意,通过使用packed,您将得到以下警告:
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!如果可以,请将Things更改为类似于C结构:
#[repr(C)]
struct Things2 {
x: u8,
y: u16,
}然后像这样初始化data。为了对齐起见,请注意额外的字节。
let data: [u8; 4] = [0x22, 0, 0x76, 0x34];https://stackoverflow.com/questions/36061560
复制相似问题