【问题标题】:Why is casting `&mut &mut i32` as `*mut *mut i32` invalid为什么将 `&mut &mut i32` 转换为 `*mut *mut i32` 无效
【发布时间】:2022-11-23 06:21:06
【问题描述】:

我可以像这样将 &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 的指针,但看起来这个转换是错误的。

为什么允许第一个演员表而不允许第二个演员表?

【问题讨论】:

  • 你可以分两步完成let xrefptr = (xrefref as *mut &mut i32) as *mut *mut i32;
  • 像这样的转换通常只能改变一个属性。例如,您可以将引用转换为指针,或更改指针的类型,但不能同时进行。
  • 谢谢@isaactfa 我可以分两步完成演员表。请随意发布示例,我会接受。

标签: rust reference


【解决方案1】:

正如@PitaJ 指出的那样,您通常一次只能进行一次转换,并且转换是不可传递的。 IE。 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

【讨论】:

    【解决方案2】:

    Rust 参考有a list of all possible casting operations。在此列表中,以下内容与此问题特别相关:

    Type of e U Cast performed by e as U
    *T *V where V: Sized Pointer to pointer cast
    &m₁ T *m₂ T Reference to pointer cast (only when m₁ is mut or m₂ is 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 2023-01-03
      • 2023-03-19
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多