gpt4 book ai didi

rust - 为什么参数的大小未知?

转载 作者:行者123 更新时间:2023-12-03 11:43:25 24 4
gpt4 key购买 nike

这是我的代码:

use std::mem::{size_of, transmute};

#[derive(Debug)]
#[repr(C)]
struct Header { // some file header
magic: u32,
data1_len: u32,
data2_len: u32,
}
fn main() {

let buffer: Vec<u8> = vec![1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0]; // whatever

let header: Header = {
unsafe { transmute(buffer[0..(size_of::<Header>())]) }
};
}

但是在编译时出现此错误:
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> main.rs:15:22
|
15 | unsafe { transmute(buffer[0..(size_of::<Header>())]) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time

实际上我的类型是大小,我是在告诉我该类型所占用的字节的精确范围。为什么编译器会提示?它应该自己得出我的类型的大小。
如何告诉编译器我要转换的大小是 Header结构的大小?

最佳答案

成为Sized是该类型的属性,而不是任何特定值。 [u8][T]通常没有大小。但是,您可能会错误地尝试转换为大小类型。

let data: [u8; size_of::<Header>()] = buffer[0..size_of::<Header>()].try_into().unwrap();
try_into通常返回结果,但是由于我们知道大小正确,因此我们可以简单地对其进行 unwrap(playground)
// The trait `TryInto` isn't in the prelude,
// so we have to import it to use its methods.
use std::convert::TryInto;
use std::mem::{size_of, transmute};

#[derive(Debug)]
#[repr(C)]
struct Header {
// some file header
magic: u32,
data1_len: u32,
data2_len: u32,
}
fn main() {
let buffer: Vec<u8> = vec![
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
]; // whatever

let header: Header = {
let data: [u8; size_of::<Header>()] = buffer[0..size_of::<Header>()].try_into().unwrap();
unsafe { transmute(data) }
};
}

注意:此步骤仅适用,因为如果 [T; N]实现 Copy,则 T实现 Copy。我们正在从向量中复制数据。如果这不是您想要的,则需要使用 Vec::splice或类似方法从向量中删除数据。他们不能同时拥有该数据。

您可能还考虑仅获取对 Header的引用,该引用实际上应在此处工作,而无需复制任何内容或修改向量。我会避免 transmute的不安全性,并使用原始指针的(稍微不那么不安全)强制转换。

不幸的是,由于 Header的对齐方式是4个字节,但 [u8]的对齐方式只有一个字节,因此在这里做的显而易见的事情是行不通的。从 &[u8]&Header的指针转换可能会导致对齐错误。 [u8; _]Header没问题的原因是 transmute按值获取数组并返回正确对齐的值。参见 pull request #38670

解决此问题的一种方法是使 Header repr(C, packed),将其对齐方式强制为一个字节。这通常会使事情变慢(但请记住:首先进行基准测试!)。我相当确定这会导致更多问题,这是由于围绕 packed结构的引用不健全而引起的,因此请多加注意。 (playground)
use std::mem::size_of;

// We can't derive anything unless we also derive Copy
// one of the downsides of this approach
#[repr(C, packed)]
struct Header {
// some file header
magic: u32,
data1_len: u32,
data2_len: u32,
}
fn main() {
let buffer: Vec<u8> = vec![
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
]; // whatever

let header: &Header = unsafe { &*(buffer[0..size_of::<Header>()].as_ptr() as *const Header) };
}

关于rust - 为什么参数的大小未知?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60143120/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com