1.17.0[][src]Function sp_std::ptr::write_unaligned

pub unsafe fn write_unaligned<T>(dst: *mut T, src: T)

Overwrites a memory location with the given value without reading or dropping the old value.

Unlike write(), the pointer may be unaligned.

write_unaligned does not drop the contents of dst. This is safe, but it could leak allocations or resources, so care should be taken not to overwrite an object that should be dropped.

Additionally, it does not drop src. Semantically, src is moved into the location pointed to by dst.

This is appropriate for initializing uninitialized memory, or overwriting memory that has previously been read with read_unaligned.

Safety

Behavior is undefined if any of the following conditions are violated:

  • dst must be valid for writes.

Note that even if T has size 0, the pointer must be non-NULL.

On packed structs

It is currently impossible to create raw pointers to unaligned fields of a packed struct.

Attempting to create a raw pointer to an unaligned struct field with an expression such as &packed.unaligned as *const FieldType creates an intermediate unaligned reference before converting that to a raw pointer. That this reference is temporary and immediately cast is inconsequential as the compiler always expects references to be properly aligned. As a result, using &packed.unaligned as *const FieldType causes immediate undefined behavior in your program.

An example of what not to do and how this relates to write_unaligned is:

#[repr(packed, C)]
struct Packed {
    _padding: u8,
    unaligned: u32,
}

let v = 0x01020304;
let mut packed: Packed = unsafe { std::mem::zeroed() };

let v = unsafe {
    // Here we attempt to take the address of a 32-bit integer which is not aligned.
    let unaligned =
        // A temporary unaligned reference is created here which results in
        // undefined behavior regardless of whether the reference is used or not.
        &mut packed.unaligned
        // Casting to a raw pointer doesn't help; the mistake already happened.
        as *mut u32;

    std::ptr::write_unaligned(unaligned, v);

    v
};

Accessing unaligned fields directly with e.g. packed.unaligned is safe however.

Examples

Write an usize value to a byte buffer:

use std::mem;

fn write_usize(x: &mut [u8], val: usize) {
    assert!(x.len() >= mem::size_of::<usize>());

    let ptr = x.as_mut_ptr() as *mut usize;

    unsafe { ptr.write_unaligned(val) }
}