我希望在以下代码中获得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
吗?
答案 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
块。