我正在从套接字读取一系列字节,我需要将n个字节的每一段作为一个项放入 struct 中.

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)吗?

推荐答案

这里的问题是y字段是16位对齐的.所以你的内存布局实际上是

x
padding
y
y

请注意,交换xy的顺序并没有帮助,因为Rust的 struct 内存布局实际上是未定义的(因此仍然是32位,这在编译器中很简单).如果你依赖它,你会得到未定义的行为.

对齐的原因在Purpose of memory alignment中解释.

通过将属性repr(packed)添加到 struct 中,可以防止对齐,但会失go 性能和获取字段引用的能力:

#[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这样的 crate 可以简化从字节中读取不同大小和长度的过程.

Rust相关问答推荐

如何容器化Linux上基于Rust的Windows应用程序的编译过程?

在特征中使用Async时,如何解决不透明类型`impl Future<;out=self>;`不满足其关联的类型边界和警告?

这个规则关于或模式到底是什么意思?如果表达片段的类型与p_i|q_i...&q;不一致,就会形成

Tokio_Postgres行上未显示退回特性的生存期,且生命周期 不够长

当对VEC;U8>;使用serde_json时,Base64编码是保护空间的好方法吗?

从未排序的链表中删除重复项的铁 rust 代码在ELSE分支的低级上做了什么?

如果变量本身不是None,如何返回;如果没有,则返回None&Quot;?

为什么比较Option<;字符串>;具有常数Option<&;str>;需要显式类型转换吗?

为什么 vec![Vec::with_capacity(n)] 为子向量创建 0 容量?

带引脚和不带引脚的比较功能

在 Rust 中忽略 None 值的正确样式

如何从trait方法返回std :: iter :: Map?

decltype、dyn、impl traits,重构时如何声明函数的返回类型

`移动||异步移动{...}`,如何知道哪个移动正在移动哪个?

我的 Axum 处理程序无法编译:未实现 IntoResponse 特征

Rust 将特性传递给依赖项

为什么1..=100返回一个范围而不是一个整数?

A 有一个函数,它在 Option<> 类型中时无法编译,但在 Option<> 类型之外会自行编译.为什么?

为什么这里需要类型注解?

为什么 `ref` 会导致此示例*取消引用*一个字段?