Macro sp_std::ptr::addr_of_mut
1.51.0 · source · pub macro addr_of_mut($place:expr) { ... }
Expand description
Create a mut
raw pointer to a place, without creating an intermediate reference.
Creating a reference with &
/&mut
is only allowed if the pointer is properly aligned
and points to initialized data. For cases where those requirements do not hold,
raw pointers should be used instead. However, &mut expr as *mut _
creates a reference
before casting it to a raw pointer, and that reference is subject to the same rules
as all other references. This macro can create a raw pointer without creating
a reference first.
The expr
in addr_of_mut!(expr)
is evaluated as a place expression, but never loads
from the place or requires the place to be dereferenceable. This means that
addr_of_mut!(*ptr)
is defined behavior even if ptr
is null, dangling, or misaligned.
Note however that addr_of_mut!((*ptr).field)
still requires the projection to
field
to be in-bounds, using the same rules as offset
.
Note that Deref
/Index
coercions (and their mutable counterparts) are applied inside
addr_of_mut!
like everywhere else, in which case a reference is created to call Deref::deref
or Index::index
, respectively. The statements above only apply when no such coercions are
applied.
§Examples
Creating a pointer to unaligned data:
use std::ptr;
#[repr(packed)]
struct Packed {
f1: u8,
f2: u16,
}
let mut packed = Packed { f1: 1, f2: 2 };
// `&mut packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
let raw_f2 = ptr::addr_of_mut!(packed.f2);
unsafe { raw_f2.write_unaligned(42); }
assert_eq!({packed.f2}, 42); // `{...}` forces copying the field instead of creating a reference.
Creating a pointer to uninitialized data:
use std::{ptr, mem::MaybeUninit};
struct Demo {
field: bool,
}
let mut uninit = MaybeUninit::<Demo>::uninit();
// `&uninit.as_mut().field` would create a reference to an uninitialized `bool`,
// and thus be Undefined Behavior!
let f1_ptr = unsafe { ptr::addr_of_mut!((*uninit.as_mut_ptr()).field) };
unsafe { f1_ptr.write(true); }
let init = unsafe { uninit.assume_init() };