W3cubDocs

/Rust

Function std::ptr::read_unaligned

pub unsafe fn read_unaligned<T>(src: *const T) -> T

Reads the value from src without moving it. This leaves the memory in src unchanged.

Unlike read, read_unaligned works with unaligned pointers.

Safety

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

  • src must be valid for reads.

  • src must point to a properly initialized value of type T.

Like read, read_unaligned creates a bitwise copy of T, regardless of whether T is Copy. If T is not Copy, using both the returned value and the value at *src can violate memory safety.

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 read_unaligned is:

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

let packed = Packed {
    _padding: 0x00,
    unaligned: 0x01020304,
};

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.
        &packed.unaligned
        // Casting to a raw pointer doesn't help; the mistake already happened.
        as *const u32;

    let v = std::ptr::read_unaligned(unaligned);

    v
};

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

Examples

Read an usize value from a byte buffer:

use std::mem;

fn read_usize(x: &[u8]) -> usize {
    assert!(x.len() >= mem::size_of::<usize>());

    let ptr = x.as_ptr() as *const usize;

    unsafe { ptr.read_unaligned() }
}

© 2010 The Rust Project Developers
Licensed under the Apache License, Version 2.0 or the MIT license, at your option.
https://doc.rust-lang.org/std/ptr/fn.read_unaligned.html