Skip to content

Commit e768fe0

Browse files
committed
document raw-addr-of operators
1 parent c164fb7 commit e768fe0

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

src/expressions/operator-expr.md

+52
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,57 @@ let a = && && mut 10;
7070
let a = & & & & mut 10;
7171
```
7272

73+
### Raw address-of operators
74+
75+
Related to the borrow operators are the raw address-of operators, which do not
76+
have first-class syntax, but are exposed via the macros `ptr::addr_of!(expr)`
77+
and `ptr::addr_of_mut!(expr)`. Like with `&`/`&mut`, the expression is evaluated
78+
in place expression context. The difference is that `&`/`&mut` create
79+
*references* of type `&T`/`&mut T`, while `ptr::addr_of!(expr)` creates a
80+
(const) raw pointer of type `*const T` and `ptr::addr_of_mut!(expr)` creates a
81+
mutable raw pointer of type `*mut T`.
82+
83+
The raw address-of operators must be used whenever the place expression denotes
84+
a place that is not properly aligned or does not store a valid value as
85+
determined by its type. In those situations, using a borrow operator would
86+
cause [undefined behavior] by creating an invalid reference, but a raw pointer
87+
may still be constructed using an address-of operator.
88+
89+
**Example of creating a raw pointer to an unaligned place (through a `packed` struct):**
90+
91+
```rust
92+
use std::ptr;
93+
94+
#[repr(packed)]
95+
struct Packed {
96+
f1: u8,
97+
f2: u16,
98+
}
99+
100+
let packed = Packed { f1: 1, f2: 2 };
101+
// `&packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
102+
let raw_f2 = ptr::addr_of!(packed.f2);
103+
assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
104+
```
105+
106+
**Example of creating a raw pointer to a place that does not contain a valid value:**
107+
108+
```rust
109+
use std::{ptr, mem::MaybeUninit};
110+
111+
struct Demo {
112+
field: bool,
113+
}
114+
115+
let mut uninit = MaybeUninit::<Demo>::uninit();
116+
// `&uninit.as_mut().field` would create a reference to an uninitialized `bool`,
117+
// and thus be Undefined Behavior!
118+
let f1_ptr = unsafe { ptr::addr_of_mut!((*uninit.as_mut_ptr()).field) };
119+
unsafe { f1_ptr.write(true); }
120+
let init = unsafe { uninit.assume_init() };
121+
```
122+
123+
73124
## The dereference operator
74125

75126
> **<sup>Syntax</sup>**\
@@ -494,6 +545,7 @@ See [this test] for an example of using this dependency.
494545
[float-float]: https://github.com/rust-lang/rust/issues/15536
495546
[Function pointer]: ../types/function-pointer.md
496547
[Function item]: ../types/function-item.md
548+
[undefined behavior]: ../behavior-considered-undefined.md
497549

498550
[_BorrowExpression_]: #borrow-operators
499551
[_DereferenceExpression_]: #the-dereference-operator

0 commit comments

Comments
 (0)