Alignment and offsetof
Every type has an alignment: an address it must start on, always a power of two. char can live
anywhere; an int must sit at an address divisible by 4; a double at one divisible by 8. This page
covers alignment as a property of types and the offsetof macro that reports where members land.
Here: alignof, alignas, and offsetof as language tools. For why padding exists, how to order
members to shrink a struct, cache-line/SIMD alignment, and packing โ see the canonical
Memory Alignment page. For the ABI / wire-format
angle (serialization, bit-fields, standard-layout rules) see
Padding and offsetof.
alignof โ a type's required alignmentโ
#include <cstddef>
alignof(char); // 1
alignof(int); // 4
alignof(double); // 8
alignof(void*); // 8 on a 64-bit target
struct Widget { char c; int i; };
alignof(Widget); // 4 โ a struct's alignment is that of its strictest member
The corollary that surprises people: because members must each be aligned, the compiler inserts
padding, so sizeof is usually larger than the sum of the member sizes.
struct Example {
char c; // offset 0
int i; // offset 4 โ 3 bytes of padding sit between them
};
sizeof(Example); // 8, not 5
offsetof โ where a member sitsโ
offsetof(Type, member) (from <cstddef>) returns the member's byte offset from the start of the
object. It makes the padding above observable:
struct Record {
char tag; // offset 0
int value; // offset 4 (after 3 padding bytes)
short count; // offset 8
};
offsetof(Record, tag); // 0
offsetof(Record, value); // 4
offsetof(Record, count); // 8
offsetof is only defined for standard-layout typesUsing it on a type with virtual functions or a non-trivial base is undefined behaviour โ those
types have no fixed, simple member offsets. Guard real code with a static_assert:
static_assert(std::is_standard_layout_v<Record>);
alignas โ requesting stronger alignmentโ
alignas(N) raises (never lowers) the alignment of a variable, member, or type. The two everyday
uses โ cache-line isolation and SIMD โ are covered on the canonical page; the syntax is:
alignas(64) int hot_counter; // start on a 64-byte boundary
struct alignas(16) Vec4 { float v[4]; }; // whole type aligned to 16 (SIMD)
Summaryโ
- Alignment is a per-type, power-of-two requirement; a struct inherits its strictest member's.
- Padding makes
sizeofexceed the member sizes;offsetoflets you see exactly where members land. offsetofis well-defined only for standard-layout types โ assert it.alignas(N)strengthens alignment; the layout-optimisation details live on the canonical page.
Relatedโ
- Memory Alignment โ padding, ordering, cache lines, SIMD, packing
- Padding and offsetof โ serialization, bit-fields, standard layout
- Fundamental Types ยท Object Layout