The hardware demands alignment
On x86, CPUs can read misaligned data — but it's slow. On ARM, misaligned reads crash the program.
So the compiler enforces a rule: every object must be stored at an address that's a multiple of its size.
A 4-byte int must start at an address divisible by 4.
An 8-byte double must start at an address divisible by 8.
When you mix types of different sizes in a struct, the compiler inserts padding bytes between
fields to satisfy this rule. Those bytes are real memory — they waste space and affect sizeof.
You're paying for them whether you know it or not.
A badly ordered struct
The fix: sort fields largest to smallest
Why the tail also gets padded
The compiler also adds padding at the end of a struct so that the total size is a multiple
of the struct's largest alignment. This matters when you have arrays of structs:
every element in struct Good arr[100] must be properly aligned.
Without tail padding, the second element in the array would start at an unaligned address.
See the bytes
The visualization below shows three scenarios: the bad struct, the optimized struct, and an array of ints. Click any byte to see exactly what it is and why it's there. Switch between scenarios with the tabs or the prev/next buttons.
__attribute__((packed)) to remove padding.
It removes alignment guarantees. Reads from packed structs may be slower (or crash on ARM).
The right answer is to reorder your fields.
Struct fields get padding bytes inserted between them for alignment. Sort largest to smallest to minimize waste.