@@ -70,6 +70,57 @@ let a = && && mut 10;
7070let 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