Macro std::mem::offset_of

source ·
pub macro offset_of($Container:ty, $($fields:tt).+ $(,)?) {
    ...
}
🔬This is a nightly-only experimental API. (offset_of #106655)
Expand description

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

Structs, enums, unions and tuples are supported.

Nested field accesses may be used, but not array indexes.

Enum variants may be traversed as if they were fields. Variants themselves do not have an offset.

Visibility is respected - all types and fields must be visible to the call site:

#![feature(offset_of)]

mod nested {
    #[repr(C)]
    pub struct Struct {
        private: u8,
    }
}

// assert_eq!(mem::offset_of!(nested::Struct, private), 0);
// ^^^ error[E0616]: field `private` of struct `Struct` is private
Run

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.:

#![feature(offset_of)]

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!(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!(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!(mem::offset_of!(Empty<u8>, 0), mem::offset_of!(Empty<i8>, 0));
Run

Examples

#![feature(offset_of)]

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);

#[repr(u8)]
enum Enum {
    A(u8, u16),
    B { one: u8, two: u16 },
}

assert_eq!(mem::offset_of!(Enum, A.0), 1);
assert_eq!(mem::offset_of!(Enum, B.two), 2);

assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0);
Run