offset_of in std::mem - Rust
Description: Expands to the offset in bytes of a field from the beginning of the given type.

## offset_of

# Macro offset_of

1.77.0 · Source

    pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) {
        ...
    }

Expand description

Expands to the offset in bytes of a field from the beginning of the given type.

The type may be a `struct`, `enum`, `union`, or tuple.

The field may be a nested field (`field1.field2`), but not an array index. The field must be visible to the call site.

The offset is returned as a `usize`.

## §Offsets of, and in, dynamically sized types

The field’s type must be `Sized`, but it may be located in a dynamically sized container. If the field type is dynamically sized, then you cannot use `offset_of!` (since the field’s alignment, and therefore its offset, may also be dynamic) and must take the offset from an actual pointer to the container instead.

    #[repr(C)]
    pub struct Struct<T: ?Sized> {
        a: u8,
        b: T,
    }

    #[derive(Debug)]
    #[repr(C, align(4))]
    struct Align4(u32);

    assert_eq!(mem::offset_of!(Struct<dyn Debug>, a), 0); // OK — Sized field
    assert_eq!(mem::offset_of!(Struct<Align4>, b), 4); // OK — not DST

    // assert_eq!(mem::offset_of!(Struct<dyn Debug>, b), 1);
    // ^^^ error[E0277]: ... cannot be known at compilation time

    // To obtain the offset of a !Sized field, examine a concrete value
    // instead of using offset_of!.
    let value: Struct<Align4> = Struct { a: 1, b: Align4(2) };
    let ref_unsized: &Struct<dyn Debug> = &value;
    let offset_of_b = unsafe {
        (&raw const ref_unsized.b).byte_offset_from_unsigned(ref_unsized)
    };
    assert_eq!(offset_of_b, 4);

If you need to obtain the offset of a field of a `!Sized` type, then, since the offset may depend on the particular value being stored (in particular, `dyn Trait` values have a dynamically-determined alignment), you must retrieve the offset from a specific reference or pointer, and so you cannot use `offset_of!` to work without one.

## §Layout is subject to change

Note that type layout is, in general, subject to change and platform-specific. If layout stability is required, consider using an explicit `repr` attribute.

Rust guarantees that the offset of a given field within a given type will not change over the lifetime of the program. However, two different compilations of the same program may result in different layouts. Also, even within a single program execution, no guarantees are made about types which are similar but not identical, e.g.:

    struct Wrapper<T, U>(T, U);

    type A = Wrapper<u8, u8>;
    type B = Wrapper<u8, i8>;

    // Not necessarily identical even though `u8` and `i8` have the same layout!
    // assert_eq!(mem::offset_of!(A, 1), mem::offset_of!(B, 1));

    #[repr(transparent)]
    struct U8(u8);

    type C = Wrapper<u8, U8>;

    // Not necessarily identical even though `u8` and `U8` have the same layout!
    // assert_eq!(mem::offset_of!(A, 1), mem::offset_of!(C, 1));

    struct Empty<T>(core::marker::PhantomData<T>);

    // Not necessarily identical even though `PhantomData` always has the same layout!
    // assert_eq!(mem::offset_of!(Empty<u8>, 0), mem::offset_of!(Empty<i8>, 0));

## §Unstable features

The following unstable features expand the functionality of `offset_of!`:

- `offset_of_enum` — allows `enum` variants to be traversed as if they were fields.
- `offset_of_slice` — allows getting the offset of a field of type `[T]`.

## §Examples

    use std::mem;
    #[repr(C)]
    struct FieldStruct {
        first: u8,
        second: u16,
        third: u8
    }

    assert_eq!(mem::offset_of!(FieldStruct, first), 0);
    assert_eq!(mem::offset_of!(FieldStruct, second), 2);
    assert_eq!(mem::offset_of!(FieldStruct, third), 4);

    #[repr(C)]
    struct NestedA {
        b: NestedB
    }

    #[repr(C)]
    struct NestedB(u8);

    assert_eq!(mem::offset_of!(NestedA, b.0), 0);