【问题标题】:Does casting pointers in Rust have the same behavior as reinterpret_cast in C++?Rust 中的转换指针是否与 C++ 中的 reinterpret_cast 具有相同的行为?
【发布时间】:2019-06-15 18:37:25
【问题描述】:

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

#[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 中使用原始指针。
  • 如果不使用原始指针,您如何处理外部内存(例如,来自内存映射文件)?
  • static cast vs reinterpret cast

标签: pointers struct rust unsafe


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 2021-09-09
    • 1970-01-01
    • 2018-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-21
    • 2021-09-10
    相关资源
    最近更新 更多