为什么将 `&mut &mut i32` 转换为 `*mut *mut i32` 无效

问题描述 投票:0回答:2

我可以像这样在 Rust 中将 &mut i32 转换为 *mut i32

fn main() {
    let mut x = 1;
    let mut xref = &mut x;
    unsafe {
        let xref_ptr = xref as *mut i32;
        *xref_ptr = 2;
    }
    println!("{}", x);
}

打印 2。

但是我无法将 &mut &mut i32 转换为 *mut *mut i32,我不明白为什么。

fn main() {
    let mut x = 1;
    let mut xref = &mut x;
    let mut xrefref = &mut xref;
    unsafe {
        let xrefptr = xrefref as *mut (*mut i32);
        **xrefptr = 2;
    }
    println!("{}", x);
}
error[E0606]: casting `&mut &mut i32` as `*mut *mut i32` is invalid
  --> src/main.rs:16:23
   |
16 |         let xrefptr = xrefref as *mut (*mut i32);
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^

如果引用是底层的指针,我期望 &mut &mut i32 是指向 i32 的指针,但看来这个转换是错误的。

为什么允许第一次演员,但不允许第二次?

rust reference unsafe
2个回答
5
投票

Rust 参考有所有可能的转换操作的列表。在此列表中,以下内容与此问题特别相关:

类型
e
U
演员阵容:
e as U
*T
*V
哪里
V: Sized
指针到指针的转换
&m₁ T
*m₂ T
参考指针转换(仅当
m₁
mut
m₂
const
时)

从这个列表中,我们看到我们可以将&mut T转换为

*mut T
我们可以将*mut T转换为
*mut V
,但是没有规则让我们从
&mut T
转换为
 *mut V
如果
T != V
相反,您可以通过结合这两个规则来分两步进行投射:

let xrefref: &mut &mut i32 = &mut xref; let xref_ptr = xrefref as *mut &mut i32 as *mut *mut i32; // &mut T -> *mut T ^^^^^^^^^^^^^^^^ // *mut T -> *mut V ^^^^^^^^^^^^^^^^ // where T = &mut i32 and V = *mut i32



4
投票
T as U

有效且

U as V
有效并不意味着
T as V
有效。
但是您只需两步即可完成转换(使用安全代码!):

let mut x = 1; let mut xref = &mut x; let mut xrefref = &mut xref; let xrefptr = (xrefref as *mut &mut i32) as *mut *mut i32; unsafe { **xrefptr = 2; } println!("{}", x); // 2

© www.soinside.com 2019 - 2024. All rights reserved.