gpt4 book ai didi

arrays - Rust:数组长度的宏

转载 作者:行者123 更新时间:2023-11-29 08:23:14 25 4
gpt4 key购买 nike

我有一个包含原始二进制数据的文件,我想将其加载到一个 4 字节长的 u32 字数组中。

可以通过在编译时包含文件的内容来实现:

let bytes = include_bytes!("audio.raw");

然后,我可以使用 transmute 将其转换为 u32 单词数组。新数组的长度显然应该是原字节数组的1/4。

let audio = unsafe { std::mem::transmute::<[u8; 63504], [u32; 15876]>(*bytes) };
// works

正如您在上面看到的,我必须对输入和输出数组的长度进行硬编码。然而,当试图避免对这些数字进行硬编码时,它不起作用:

let audio = unsafe { std::mem::transmute::<[u8; bytes.len()], [u32; bytes.len()/4]>(*bytes) };
// error: non-constant value

.len() 似乎是在运行时调用的,由于在 Rust 中不能分配动态数组,因此会产生错误。然而理论上,应该有一种方法可以在编译阶段计算出所需的长度,因为 bytes 数组的长度是固定的。所以我的问题是:是否有一个宏可以返回静态数组的长度?

(我完全清楚向量可以进行动态分配,我的问题明确是关于固定大小的数组。)

Sample code (include_bytes 替换为硬编码数组):

fn main() {
// let bytes = include_bytes!("audio.raw");
let bytes = [1, 0, 0, 0, 2, 0, 0, 0];

// works:
let audio = unsafe { std::mem::transmute::<[u8; 8], [u32; 2]>(bytes) };

// error:
let audio = unsafe { std::mem::transmute::<[u8; bytes.len()], [u32; bytes.len() / 4]>(bytes) };

println!("{}", audio[1]);
}

最佳答案

一般来说,不复制就不可能将u8数组转换成u32数组。

此转换仅在以下条件下有效:

  1. 对齐数组需要对齐以容纳u32,这通常意味着它需要从四的倍数的地址开始。对于使用 include_bytes!() 宏创建的字节数组,不能保证合适的对齐方式。这可以使用此代码(playgorund:

    let bytes: [u8; 5] = [1, 2, 3, 4, 5];
    dbg!(bytes.as_ptr().align_offset(std::mem::align_of::<u32>()));

    当我尝试在 Playground 上运行它时,结果为 1,这意味着字节数组未对齐以容纳 u32,但无法保证结果。

  2. 字节序。数组中的字节必须表示 32 位整数,其字节序必须与目标架构字节序相匹配。如果您从文件中加载的数据采用小端字节序,则任何将数据解释为 32 位整数而不进行任何转换的代码都只能在小端字节序平台上运行。

  3. 长度。字节数组的长度需要是u32大小的倍数,即4的倍数。

如果满足这些条件,理论上您可以使用以下代码将字节数组转换为 u32 的切片:

let audio = unsafe {
let ptr = bytes.as_ptr() as *const u32;
let factor = std::mem::size_of::<u32>() / std::mem::size_of::<u8>();
let len = bytes.len() / factor;
if ptr.align_offset(std::mem::align_of::<u32>()) == 0
&& bytes.len() % factor == 0
&& cfg!(target_endian = "little")
{
std::slice::from_raw_parts(ptr, len)
} else {
// Perform proper conversion.
}
};

但是,这似乎不值得这么麻烦——无论如何您都需要实现真正的转换代码。

我的建议是使用实际的音频文件格式,并使用库加载它——这将为您省去各种麻烦。

关于arrays - Rust:数组长度的宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57236327/

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