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



我可以像这样在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引用包含所有可能的强制转换操作的列表。在这个列表中,以下是与这个问题特别相关的:

e U e as U
*T *VwhereV: Sized 指针到指针的转换
&m₁ T *m₂ T 对指针强制转换的引用(仅当m₁mutm₂const时)

正如@PitaJ指出的那样,通常一次只允许进行一次强制转换,并且强制转换不具有传递性。也就是说,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

最新更新