CMemory Alignment & Padding

Memory Alignment & Padding

Modern CPUs do not read memory one byte at a time — they read it in fixed-size chunks (often 4 or 8 bytes) aligned to specific address boundaries. A 4-byte int stored at an address that is a multiple of 4 can be fetched in a single memory access. Misaligned data — say, a 4-byte int starting at address 3 — may require the CPU to perform two separate reads and stitch the result together, or on some architectures may not be allowed at all and trigger a hardware fault. To avoid this, the C compiler carefully places every variable and struct member at an address that respects its type's alignment requirement.
Struct Padding
To keep every member correctly aligned, the compiler is allowed to insert invisible, unused padding bytes between struct members (and sometimes after the last member). This means sizeof(struct) can be larger — sometimes much larger — than the simple sum of its members' sizes.

C
#include <stdio.h>

struct example {
    char a;   // 1 byte
    int b;    // 4 bytes, needs 4-byte alignment
    char c;   // 1 byte
};

int main(void) {
    printf("sizeof(char) = %zu\n", sizeof(char));
    printf("sizeof(int)  = %zu\n", sizeof(int));
    printf("naive sum    = %zu\n", sizeof(char) + sizeof(int) + sizeof(char));
    printf("sizeof(struct example) = %zu\n", sizeof(struct example));
    return 0;
}
sizeof(char) = 1
sizeof(int)  = 4
naive sum    = 6
sizeof(struct example) = 12

On a typical 64-bit platform this struct is 12 bytes, not 6. The layout in memory looks like this:

Text
offset 0: a           (1 byte)
offset 1: [padding]   (3 bytes, so 'b' can start on a 4-byte boundary)
offset 4: b           (4 bytes)
offset 8: c           (1 byte)
offset 9: [padding]   (3 bytes, so the struct's total size is a multiple
                        of its largest member's alignment -- 4 here)
Reordering Members to Reduce Padding

Because padding is driven purely by member order and alignment, you can often shrink a struct simply by reordering its fields — largest members first, smallest last — with no change in behavior:

C
// Before: 12 bytes due to padding around the single char members
struct bad_layout {
    char a;
    int b;
    char c;
};

// After: 8 bytes -- both chars pack into the same 4-byte slot
struct good_layout {
    int b;
    char a;
    char c;
};
Order struct members from largest to smallest
As a habit, declare struct members roughly in decreasing order of size (pointers and `double`/`long` first, then `int`, then short, then char). This is a purely mechanical change that can noticeably shrink memory usage for large arrays of structs, with zero cost to readability.
_Alignof and _Alignas (C11)
C11 added two keywords for working with alignment directly. _Alignof(type) reports a type's required alignment in bytes, and _Alignas(n) forces a variable or struct member to be aligned to a specific boundary — useful for things like SIMD data or matching a hardware-mandated layout.

C
#include <stdalign.h>
#include <stdio.h>

int main(void) {
    printf("alignof(int) = %zu\n", _Alignof(int));
    printf("alignof(double) = %zu\n", _Alignof(double));

    _Alignas(16) char buffer[64]; // force 16-byte alignment
    printf("buffer address is 16-byte aligned: %d\n",
           ((size_t)buffer % 16) == 0);

    return 0;
}
Padding is compiler- and platform-dependent
The exact padding a compiler inserts is not mandated by the C standard — it depends on the target architecture's alignment rules and the compiler's own layout algorithm. Never assume a specific struct layout across compilers or platforms; if you need a guaranteed byte-for-byte layout (e.g. for a network protocol or file format), use explicit fixed-width types and serialize fields individually rather than relying on sizeof(struct).
  • CPUs read aligned memory more efficiently, and some architectures fault on misaligned access entirely

  • The compiler inserts invisible padding bytes between struct members to keep each one properly aligned

  • sizeof(struct) can be larger than the sum of its members due to this padding

  • Ordering struct members from largest to smallest often reduces or eliminates unnecessary padding

  • _Alignof and _Alignas (C11) let you query and control alignment explicitly