如何将一个整数值后面跟着一个由该值组成的字节串的长度复制为任意字节的C代码转换为任意字节

  • 本文关键字:字节 一个 任意 转换 代码 复制 整数 c rust
  • 更新时间 :
  • 英文 :


我使用这个C代码将几个值编码为一个字节字符串:

unsigned char *buf = malloc(10);
*(unsigned int *)buf = 6;
memcpy(buf + 4, source, 6);
// Repeat for more values...

它复制一个uint32,该值的长度后跟一个由该值组成的字节字符串。

在Rust中如何做到这一点?据我所知,似乎没有一种简单的方法可以以任意的排列和宽度来处理内存。

user4815162342的答案提供了直接翻译。这里有一个更惯用的Rust方法:

use byteorder::{BigEndian, WriteBytesExt}; // 1.3.4
use std::io::Write;
fn main() {
let source = [0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let mut buff = Vec::with_capacity(10);
buff.write_i32::<BigEndian>(6).unwrap();
buff.write(&source).unwrap();
}

这是因为Write特性是为Vec<u8>实现的。

使用byteorder机箱可以指定要写入长度的字节序。

与C版本有一些不同:

  • write将根据需要扩展缓冲区的大小(尽管如果您从一开始就使用所需的大小创建缓冲区,则会更高效(

  • CCD_ 6返回指示是否存在错误的CCD_。在这个示例中,我选择了打开结果,如果出现错误,这会引起恐慌。然而,正如@shepmaster所指出的,writeVec上的当前实现只返回一个Ok变体,因此您可以通过如下丢弃它来减少检查结果的开销:

    let _ = buff.write(&source);
    

您的示例非常低级;如果你告诉我们你想要实现什么样的高级目标,这将有所帮助,我们可能会推荐一种在Rust中实现这一目标的优雅方法。

然而,Rust是一种系统语言,因此将代码翻译成Rust肯定是可能的,只要考虑到它:a(不安全,b(不优雅。所谓不安全,我的意思是,您实际上需要使用unsafe来允许对指针进行无保护的写入,并且象征性地说,错误可能很容易导致未定义的行为。它并不优雅,因为通常有更好的方法来实现相同的功能。

话虽如此,这里是C代码的直接翻译:

use std::alloc::{self, Layout};
use std::{mem, ptr};
fn main() {
let source = [0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9];
unsafe {
let layout = Layout::from_size_align(10, mem::align_of::<i32>()).unwrap();
let buf = alloc::alloc(layout);     // buf = malloc(10)
*(buf as *mut i32) = 6;             // *(unsigned int *)buf = 6;
ptr::copy(source.as_ptr(), buf, 6); // memcpy(buf, source, 6);
// fill the rest of buf with something, otherwise UB on read
// use buf...
alloc::dealloc(buf, layout);        // free(buf)
}
}

这类代码通常不会在Rust程序中编写。它用于特殊情况,例如在实现一个现有板条箱尚未覆盖的安全抽象板条箱时,并经过极其谨慎的审查。例如,在这个答案中编写的代码最初包含一个由评论者善意指出的非琐碎错误(现已修复(。此外,该代码没有检查分配失败(但问题中的原始C代码也没有(。

相关内容

最新更新