我可以像这样在 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 参考有所有可能的转换操作的列表。在此列表中,以下内容与此问题特别相关:
类型
|
|
演员阵容:
|
---|---|---|
|
哪里
|
指针到指针的转换 |
|
|
参考指针转换(仅当 为 或 为 时) |
从这个列表中,我们看到我们可以将&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
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