Struct Padding Visualizer
Visualize C struct member offsets, padding and total size.
natural alignment (System V-style) · long = 4 bytes · pointers = 4 bytes
| Member | Offset | Size | Pad before |
|---|---|---|---|
| flags | 0 | 1 | 0 |
| count | 4 | 4 | 3 |
| id | 8 | 2 | 0 |
| name[8] | 10 | 8 | 0 |
sizeof = 20 · alignment 4 · 5 bytes padding (25 %)
This tool lays out a C struct the way a natural-alignment compiler does: paste the members and read each field's offset, the padding inserted before it, and the final sizeof — for 32- or 64-bit targets, with a byte map that paints padding amber. The demo struct wastes 5 of its 12 bytes; reordering reclaims them.
How it works
Under natural alignment each member must start at an offset divisible by its own size (capped at the word size), so the compiler inserts invisible bytes before misaligned members. The struct's total size then rounds up to the largest member alignment, so that consecutive array elements stay aligned too. This tool applies exactly those rules — long as 4/8 bytes per LP64, pointers at word size — and reports every inserted byte.
Because padding is invisible in source code, it is a classic source of surprises: structs that don't match wire formats, memcmp comparing garbage bytes, and doubled memory footprints from unlucky member ordering.
Worked example
offsets: flags 0 · count 4 (+3 pad) · id 8
sizeof = 12 (5 bytes padding) — reordered largest-first: 8
Parameters
| Parameter | Value | Notes |
|---|---|---|
| Rule | offset % min(size, word) == 0 | natural alignment |
| Tail padding | size rounds to max align | keeps arrays aligned |
| long | 4 B (32-bit) / 8 B (64-bit LP64) | MSVC differs: always 4 |
| Pointers | word size | 4 / 8 bytes |
| Supported | stdint types, char/short/int/long, float/double, arrays, pointers |
C reference
#include <stddef.h> /* offsetof */
struct sample {
uint8_t flags; /* offset 0 */
uint32_t count; /* offset 4 (3 pad) */
uint16_t id; /* offset 8 */
}; /* sizeof = 12 (2 tail pad) */
_Static_assert(offsetof(struct sample, count) == 4, "layout");
_Static_assert(sizeof(struct sample) == 12, "size");FAQ
▸Why does the compiler insert padding at all?
Because most CPUs load an N-byte value fastest (or only correctly) from an address divisible by N. The compiler aligns each member to its natural boundary and pads the struct's tail so arrays of it stay aligned — trading bytes for guaranteed-safe access.
▸How do I minimize padding?
Order members from largest to smallest alignment. The example struct {uint8_t; uint32_t; uint16_t;} occupies 12 bytes, but reordering to {uint32_t; uint16_t; uint8_t;} drops it to 8 — the visualizer's byte map makes such wins visible immediately.
▸Which alignment rules does this tool assume?
Natural alignment as used by System V-style ABIs (GCC/Clang on x86-64, ARM EABI): each member aligns to its own size, long is 4 bytes on 32-bit and 8 on 64-bit (LP64), pointers match the word size. Note MSVC on Windows keeps long at 4 bytes even on 64-bit, and #pragma pack changes everything.
▸Why does struct layout matter for protocols and file formats?
Casting a raw byte buffer onto a struct only works when both sides agree on layout — padding silently shifts fields. For wire formats, either serialize field by field, or use packed structs knowingly and accept the unaligned-access cost.
▸Is my data uploaded?
No. Parsing and layout run locally in your browser.