主要观点:Rust 语言中有值表达式和位置表达式两种,在安全代码中无需过多考虑其区别,但在不安全代码中需要正确理解。通过添加新语法可使这种隐含区别显式化,如用不同语法解释表达式,明确位置表达式和值表达式的概念及作用。
关键信息:
- 不稳定的“原始借用”操作符
&raw const及ptr::addr_of!宏,用于展示位置和值的相互作用。 - 示例中
let x = MyStruct { field: 42 }; let ptr = &raw const x.field;因结构体字段未对齐导致*ptr有未定义行为,而let ptr_copy = &raw const *ptr则无问题,解释了位置和值表达式的差异及隐含的load操作。 - 不同语法中,值表达式计算值,如字面量、计算式等,位置表达式表示内存位置,如本地变量、
*操作结果等,let new_var = my_var;在语法中不是有效语句,需添加load。 _模式与位置表达式结合会导致意外行为,如let _ = *ptr;可接受,let _val = *ptr;有未定义行为,match语句也有类似情况。unsafe块会使表达式成为值表达式,如unsafe { *ptr }会加载指针。- 当位置表达式出现在值表达式预期位置或值表达式出现在位置表达式预期位置时,Rust 编译器会隐式转换程序,安全代码中可忽略,不安全代码中需理解其作用。
重要细节:
- 语法中
*操作在值表达式上工作时需先load获取值,在位置表达式上工作时产生位置表达式。 - 位置表达式可产生未对齐位置,可转换为原始指针值,但从未对齐位置加载或存储是不合法的。
- 在
&操作中,值表达式15会被隐式转换为临时本地变量,除赋值运算符左操作数外。 - Rust 编译器在编译为 MIR 形式时会隐式进行去糖操作,
load操作有时被称为“位置到值强制转换”。 - 位置表达式
.字段表达式在某些情况下会关心指向现有内存,但通常应避免在悬空指针上进行字段投影。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。