是否有通用的Rust指针类型可以存储任何其他类型的指针,类似于C的void *?

时间:2019-06-04 10:10:57

标签: pointers rust

我想为我的板条箱创建C FFI API,但尚不清楚强制转换指针的安全性。伪代码:

#[no_mangle]
extern "C" fn f(...) -> *mut c_void {
    let t: Box<T> = ...;
    let p = Box::into_raw(t);
    p as *mut c_void
}

这可以按预期工作,但是它的安全性如何?在C或C ++中,有一个特殊的void *指针,并且C ++标准声明可以安全地对其进行强制转换。 sizeof(void *)可能不等于sizeof(T *),但是可以保证sizeof(void *)> = sizeof(T *)

Rust呢?是否有关于指针std::mem::size_of的保证或指针之间的安全转换?还是所有指针的实现大小都相等,等于usize

“通用”是指您可以转换X *而不会丢失任何内容。我不在乎类型信息;我关心的是指向不同事物的指针的大小不同,例如16位天中的near / far指针。

4.10说

  

将“ pointer to cv T”转换为“ pointer to cv void”的结果指向类型为T的对象所在的存储位置的起始位置,

不可能sizeof(void *) < sizeof(T *),因为那样就不可能拥有存储位置的真实地址。

1 个答案:

答案 0 :(得分:4)

否。

Rust的原始指针(和引用)目前有两种形式:

  • 薄(一个本地大小的整数)
  • fat(两个本地大小的整数)
use std::mem;

fn main() {
    println!("{}", mem::size_of::<*const u8>());   //  8
    println!("{}", mem::size_of::<*const [u8]>()); // 16
}

没有允许同时存储两者的类型。甚至mem::transmute的大锤子也行不通:

use std::mem;

unsafe fn example(mut thin: *const u8, mut fat: *const [u8]) {
    fat = mem::transmute(thin);
    thin = mem::transmute(fat);
}
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
 --> src/main.rs:4:11
  |
4 |     fat = mem::transmute(thin);
  |           ^^^^^^^^^^^^^^
  |
  = note: source type: `*const u8` (64 bits)
  = note: target type: `*const [u8]` (128 bits)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
 --> src/main.rs:5:12
  |
5 |     thin = mem::transmute(fat);
  |            ^^^^^^^^^^^^^^
  |
  = note: source type: `*const [u8]` (128 bits)
  = note: target type: `*const u8` (64 bits)

由于胖指针的布局是Rust特定的概念,因此绝不应通过FFI访问它们。这意味着只应使用细指针,所有细指针都具有统一的已知大小。

另请参阅: