Skip to content

Commit 9e02fd9

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

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

src/expressions/operator-expr.md

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

75119
> **<sup>Syntax</sup>**\
@@ -494,6 +538,7 @@ See [this test] for an example of using this dependency.
494538
[float-float]: https://github.com/rust-lang/rust/issues/15536
495539
[Function pointer]: ../types/function-pointer.md
496540
[Function item]: ../types/function-item.md
541+
[undefined behavior]: ../behavior-considered-undefined.md
497542

498543
[_BorrowExpression_]: #borrow-operators
499544
[_DereferenceExpression_]: #the-dereference-operator

0 commit comments

Comments
 (0)