如何将结构引用转换为isize?

时间:2017-04-14 20:27:40

标签: rust

我希望在以下代码中获得b

unsafe {
    struct Test {
        num: i32,
    }
    let a = Test { num: 0 };
    let b = &mut a as isize;
}

但是会导致以下错误消息。

error: casting `&on_create::Test` as `isize` is invalid
   --> main.rs:181:15
    |
181 |       let b = &a as isize;
    |    

我认为它会被强制转移到*const _,然后应用ptr-addr-cast。我错过了什么?我应该使用mem::transmute吗?

2 个答案:

答案 0 :(得分:5)

  

我认为它会被强制转移到*const _,然后应用ptr-addr-cast。 ...

首先,隐含的强制并不是在任何地方都会发生,当然也不会像你注意到的那样在e as T这样的表达式中。强制发生的地方,称为coercion sites,通常是你评估表达的地方,例如。

  • let / const / static声明的RHS:

    let x = foo
    //      ^~~
    
  • 函数的参数:

    foo(bar)
    //  ^~~
    
  • 返回表达式:

    fn f() -> u32 {
        foo
    //  ^~~
    }
    
  • struct / array / tuple literals:

       [foo, bar, baz]
    //  ^~~  ^~~  ^~~
       (foo, bar, baz)
    //  ^~~  ^~~  ^~~
       Foo { field: foo }
    //              ^~~
    
  • 块中的最后一个表达式:

    { ...; foo }
    //     ^~~
    

foo as isize不在此列表中。

其次,即使在任何地方都允许隐式强制,这并不意味着Rust应该选择强制转换为使转换有效的类型。 &mut Test可以强制为&Test*mut Test*const Test&mut SomeTrait等,编译器需要检查所有这些内容!这只有在告诉表达式强制要求的类型时才有效:

#![feature(type_ascription)]

let b = {&a}: *const _ as isize;
//       ^~ ^~~~~~~~~~
//        |   we explicitly make the type a const raw pointer
//        |                             using type-ascription
//        a coercion site

但这与规范解决方案&a as *const _ as isize没什么区别。

答案 1 :(得分:4)

您需要使用显式转换; "链"转换/强制通常不会(永远?)工作:

struct Test {
    num: i32,
}
let a = Test { num: 0 };
let b = &a as *const _ as isize;

由于没有可变性的原因,我已将其删除。此代码段中也没有不安全的行为,因此不需要unsafe块。