Under The Hood
backend rust Rust 1.x

Memory Layout: Struct Padding, Field Reordering, #[repr(C)], #[repr(packed)]

Last updated
Prerequisites:
Rust structs and types
Understanding of memory alignment and C ABI
  • rust
  • memory-layout
  • repr-c
  • repr-packed
  • padding
  • alignment

Read at your depth

The practical view

Rust structs have a default layout: the compiler can REORDER fields to minimize padding (size = sum of field sizes, rounded up to alignment). The layout is unspecified by default — you can't rely on field order or offsets. #[repr(C)] gives C-compatible layout: fields in declaration order, with C's alignment/padding rules — required for FFI and for matching C structs. #[repr(packed)] removes padding (fields tightly packed) — saves memory but can cause unaligned access (and performance/UB issues on some platforms). #[repr(align(N))] forces a minimum alignment. Use std::mem::size_of and offset_of to check layouts.

The same idea in other frameworks

react equivalent
N/A — Rust language feature.

Legacy vs modern

Default repr(Rust) layout vs #[repr(C)]

The default layout reorders fields to pack tightly; #[repr(C)] preserves declaration order with C padding — needed for FFI.

before → after
Assuming field order for FFI
struct Point { x: u8, y: u64, z: u8 } // ❌ OLD: order NOT guaranteed
#[repr(C)] for FFI
#[repr(C)]
struct Point { x: u8, y: u64, z: u8 } // ✅ NEW: C layout, field order fixed

Interview gotchas

Context

This tests the layout model — interviewers want the field-reordering freedom and why only #[repr(C)] provides the ABI guarantee C code needs.

The mechanical answer

The default repr(Rust) layout gives the compiler (rustc + LLVM) the freedom to reorder fields and choose padding to minimize size — an optimization that can change between compiler versions. Because the layout is unspecified and unstable, passing such a struct across an FFI boundary is unsafe: the C side expects a specific layout (declaration order with C alignment/padding), and a reordered Rust struct would be misinterpreted. #[repr(C)] pins the layout to the C rules: exact field order, C alignment, and trailing padding — making the struct ABI-compatible. The same concern applies to serializing structs directly to bytes, reading binary formats, or relying on offset_of for a specific member. If you need a stable layout for any of those, use #[repr(C)] (or repr(packed)/repr(align) as appropriate).

Trap

The naive answer is 'struct fields are in declaration order'. Rust's default layout is explicitly unspecified and may reorder. Another trap: thinking size_of alone tells you the layout — two different layouts can have the same size; offsets matter. Candidates who explain the reordering freedom and the FFI guarantee show real understanding.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.