首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我可以将一个字节数组反序列化为一个结构吗?

我可以将一个字节数组反序列化为一个结构吗?
EN

Stack Overflow用户
提问于 2016-03-17 13:11:42
回答 4查看 10.2K关注 0票数 16

我正在从套接字中读取一系列字节,我需要将n个字节的每一个段作为一个结构中的一个项。

代码语言:javascript
复制
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)吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-03-17 13:21:57

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

代码语言:javascript
复制
x
padding
y
y

请注意,交换xy的顺序没有帮助,因为Rust的内存布局实际上是未定义的(因此,除了编译器中的简单性之外,仍然是32位)。如果您依赖它,您将得到未定义的行为。

内存对齐的目的解释了对齐的原因。

通过将属性repr(packed)添加到您的结构中,可以防止对齐的发生,但是您将失去性能和获取字段引用的能力:

代码语言:javascript
复制
#[repr(packed)]
struct Things {
    x: u8,
    y: u16,
}

最好的方法是根本不使用transmute,而是手动提取值,并希望优化器能够快速实现:

代码语言:javascript
复制
let foobar = Things {
    x: array[0],
    y: ((array[1] as u16) << 8) | (array[2] as u16),
};

字节顺序这样的板条箱可以简化从字节读取不同大小和大小的数据的过程。

票数 16
EN

Stack Overflow用户

发布于 2022-04-12 22:33:25

二进制代码和serde可以简单地完成这个任务。

代码语言:javascript
复制
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);
}

这对于将结构序列化为字节也很有效。

代码语言:javascript
复制
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);

}
票数 3
EN

Stack Overflow用户

发布于 2022-03-16 13:39:19

在处理具有char数组的结构时,我在使用byteorder机箱时遇到了问题。我无法通过编译器错误。最后我的演员是这样的:

代码语言:javascript
复制
#[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,您将得到以下警告:

代码语言:javascript
复制
   = 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结构:

代码语言:javascript
复制
#[repr(C)]
struct Things2 {
    x: u8,
    y: u16,    
}

然后像这样初始化data。为了对齐起见,请注意额外的字节。

代码语言:javascript
复制
let data: [u8; 4] = [0x22, 0, 0x76, 0x34];
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36061560

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档