Skip to content

Commit 797bb9f

Browse files
RalfJungjoshtriplett
authored andcommitted
document raw-addr-of operators
1 parent 96a4a64 commit 797bb9f

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

src/expressions/operator-expr.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,50 @@ let a = && && mut 10;
7979
let a = & & & & mut 10;
8080
```
8181

82+
### Raw address-of operators
83+
84+
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)`.
85+
Like with `&`/`&mut`, the expression is evaluated in place expression context.
86+
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`.
87+
88+
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.
89+
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.
90+
91+
**Example of creating a raw pointer to an unaligned place (through a `packed` struct):**
92+
93+
```rust
94+
use std::ptr;
95+
96+
#[repr(packed)]
97+
struct Packed {
98+
f1: u8,
99+
f2: u16,
100+
}
101+
102+
let packed = Packed { f1: 1, f2: 2 };
103+
// `&packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
104+
let raw_f2 = ptr::addr_of!(packed.f2);
105+
assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
106+
```
107+
108+
**Example of creating a raw pointer to a place that does not contain a valid value:**
109+
110+
```rust
111+
use std::{ptr, mem::MaybeUninit};
112+
113+
struct Demo {
114+
field: bool,
115+
}
116+
117+
let mut uninit = MaybeUninit::<Demo>::uninit();
118+
// `&uninit.as_mut().field` would create a reference to an uninitialized `bool`,
119+
// and thus be Undefined Behavior!
120+
let f1_ptr = unsafe { ptr::addr_of_mut!((*uninit.as_mut_ptr()).field) };
121+
unsafe { f1_ptr.write(true); }
122+
let init = unsafe { uninit.assume_init() };
123+
```
124+
125+
82126
## The dereference operator
83127

84128
> **<sup>Syntax</sup>**\
@@ -605,6 +649,7 @@ See [this test] for an example of using this dependency.
605649
[float-float]: https://github.com/rust-lang/rust/issues/15536
606650
[Function pointer]: ../types/function-pointer.md
607651
[Function item]: ../types/function-item.md
652+
[undefined behavior]: ../behavior-considered-undefined.md
608653

609654
[_BorrowExpression_]: #borrow-operators
610655
[_DereferenceExpression_]: #the-dereference-operator

0 commit comments

Comments
 (0)