Skip to content

Commit 36d7f93

Browse files
committed
document raw-addr-of operators
1 parent 9d289c0 commit 36d7f93

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
@@ -71,6 +71,50 @@ let a = && && mut 10;
7171
let a = & & & & mut 10;
7272
```
7373

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

76120
> **<sup>Syntax</sup>**\
@@ -595,6 +639,7 @@ See [this test] for an example of using this dependency.
595639
[float-float]: https://github.com/rust-lang/rust/issues/15536
596640
[Function pointer]: ../types/function-pointer.md
597641
[Function item]: ../types/function-item.md
642+
[undefined behavior]: ../behavior-considered-undefined.md
598643

599644
[_BorrowExpression_]: #borrow-operators
600645
[_DereferenceExpression_]: #the-dereference-operator

0 commit comments

Comments
 (0)