cpp core · high

C Fundamentals: Struct Padding, Union, Bit Fields, alignas, Pointer Arithmetic

C fundamentals for C++ engineers. Struct padding: each member aligned to its natural alignment (char=1, int=4, double=8); trailing padding added so struct size is multiple of largest member's alignment. Sort members largest-first to minimize wasted bytes. Union: all members at offset 0; sizeof = largest member; only one member active; reading non-active member = UB in C++ (use std::variant or bit_cast<>). Bit fields: unsigned x:N packs N bits; can't take address; no cross-platform binary layout guarantee. alignas(N): override alignment (SIMD: 16/32 bytes, cache line: 64 bytes). alignof(T): query alignment. static_assert to verify. __attribute__((packed)): removes padding; unaligned access = UB/crash on ARM; use memcpy. Pointer arithmetic: units of sizeof(T). __restrict: no aliasing hint; enables auto-vectorization. volatile: prevents caching of access; for HW registers and signal flags.

🔑 Key line

Struct padding: members aligned to natural alignment; sort largest-first to minimize. Union: all members at same address; only one active (UB to read other in C++). Bit fields: unsigned x:N; can't take address; layout impl-defined. alignas(N) for SIMD/cache-line; __attribute__((packed)) eliminates padding with unaligned risk.

The code

// C fundamentals: Structs, Unions, Bit Fields, Padding/Alignment
// struct layout — compiler adds padding for alignment
struct Bad { // bad ordering — lots of padding
char a; // 1 byte
// 3 bytes padding (int needs 4-byte alignment)
int b; // 4 bytes
char c; // 1 byte
// 3 bytes padding (struct total must align to 4)
}; // sizeof(Bad) = 12
struct Good { // reorder largest first
int b; // 4 bytes
char a; // 1 byte
char c; // 1 byte
// 2 bytes padding (total aligns to 4)
}; // sizeof(Good) = 8
// Union — all members share the SAME memory
union Data {
int i; // 4 bytes
float f; // 4 bytes
char bytes[4]; // 4 bytes ← read any member's bytes
};
Data d;
d.i = 1;
d.f; // undefined behavior! reading non-active member
d.bytes[0]; // OK in C (implementation-defined in C++)
// Bit fields — pack integers into fewer bits
struct Flags {
unsigned int enabled : 1; // 1 bit
unsigned int priority : 3; // 3 bits (0-7)
unsigned int type_id : 4; // 4 bits (0-15)
// total: 8 bits in one int
};
Flags f;
f.enabled = 1;
f.priority = 5;
// Alignment control:
alignas(64) char cache_line_buf[64]; // aligned to cache line
struct alignas(16) Vec4 {
float x, y, z, w;
}; // SIMD-ready
static_assert(alignof(Vec4) == 16);
// __attribute__((packed)) — no padding (GCC/Clang)
struct __attribute__((packed)) Compact {
char a;
int b;
char c;
}; // sizeof=6
// DANGER: unaligned int read may be slow or crash on ARM

What this lesson walks through

  1. 01Padding — the compiler aligns each member
  2. 02Reorder largest-first → less padding
  3. 03Union — all members share ONE memory
  4. 04Bit fields — pack values into single bits
  5. 05alignas / alignof — control the boundary
  6. 06packed — no padding, but unaligned

Each member must sit at an offset that's a multiple of its alignment (int → 4). Order char, int, char and the compiler inserts padding, so sizeof balloons to 12 — only 6 bytes are real data.

See it animated — step by step, at your own pace

Unlock the full interactive walkthrough of C Fundamentals: Struct Padding, Union, Bit Fields, alignas, Pointer Arithmetic and 100+ animated C++ interview lessons.

← Previous
Strict Aliasing & Type Punning
Next →
Two-Phase Lookup: Why a Dependent Base's Member Won't Compile