pointers - Rust 中的指针转换是否与 C++ 中的 reinterpret_cast 具有相同的行为?

标签 pointers struct rust unsafe

我在我的代码中定义了这个结构:

#[repr(align(4))]
struct MetaDataDefn {
  cncVersion: i32,
  toDriverBufferLength: i32,
  toClientsBufferLength: i32,
  counterMetadataBufferLength: i32,
  counterValuesBuferLength: i32,
  clientLivenessTimeout: i64,
  startTimestamp: i64,
  pid: i64
}

我有一个函数,它接受一个指向内存块的原始指针,其中第一个字节对应于具有相同布局的结构。 我认为如果我将 u8 指针转换为结构指针,我会得到与在 C++ 中执行 reinterpret_cast 相同的结果。但是,我认为情况并非如此,我对这里发生的事情有点困惑。这是函数体(函数接收的指针是cncFilePtr):

let metadata = unsafe { cncFilePtr as *mut MetaDataDefn };

// This works
let cncVersion = unsafe { (*(cncFilePtr as *mut i32)) };
println!("CNC Version: {}", cncVersion);

//This prints a different number than the previous code
println!("CNC version (other way): {}", unsafe { (*metadata).cncVersion });

如您所见,将前 4 个字节转换为 i32 然后打印结果与将整个内容转换为 MetaDataDefn 并访问类型为 i32 的第一个成员(我的理解是这两种方法应该给出相同的结果)

我的问题是:为什么结果不一样? Rust 中的指针转换与 C++ 中的 reinterpret_cast 不同吗(我来自 C++ 背景)?

最佳答案

通常,Rust 不保证结构在内存中的表示方式。它可以重新排序字段以使它们打包得更紧密,并且理论上甚至可以根据您的应用程序实际访问它们的方式优化字段顺序。

您可以通过添加 #[repr(C)] 属性来固定顺序,使其表现得像 C:

#[repr(C)]
#[repr(align(4))]
struct MetaDataDefn { ... }

这样,两个指针将给出相同的结果,因为这保证了 cncVersion 首先出现。

关于pointers - Rust 中的指针转换是否与 C++ 中的 reinterpret_cast 具有相同的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56613171/

相关文章:

c# - 如何在 C# 中传递作为结构的可选参数

c - Malloc 结构体的元素

pagination - Rust:BTreeMap 相等性+不等性范围查询

c++ - 到处使用共享指针有什么陷阱?

c++ - C++ 中的自动指针 (auto_ptr)

c - c中struct中struct的指针

mysql - `?` 运算符只能在返回 `Result` 或 `Option` (或实现 `std::ops::Try` 的其他类型)的函数中使用

c++ - 是否可以将 char[][] 传递给请求 char** 的函数?

c - 我不明白 SPI 驱动程序中的一行代码

html - 是否有 html5ever 的替代库接受一个字符串并返回一个可查询的对象?