Memory Layout Visualizer
See exactly how compilers lay out your structs, unions, and enums in memory. Visualize padding, alignment gaps, and byte offsets for C, C++, and Rust — with OS-aware type sizes, ABI comparison, step-by-step trace, and field reordering to minimize wasted space.
Processed entirely in your browser
LP64
Tools
Struct Fields
Optimization AvailableSave 8B by reordering
Total Size24B
Padding10B(41.7%)
Alignment8B
Fields4
Memory Layout (byte-level)
Padding
+0
+1
+2
+3
+4
+5
+6
+7
0x00
a
pad
pad
pad
b
0x08
c
pad
pad
pad
pad
pad
pad
pad
0x10
d
Field Details
| Field | Type | Offset | Size | Align |
|---|---|---|---|---|
a | char | 0 | 1B | 1 |
b | int | 4 | 4B | 4 |
c | char | 8 | 1B | 1 |
d | double | 16 | 8B | 8 |
Struct Definition
struct MyStruct {
char a;
int b;
char c;
double d;
};
sizeof(MyStruct) = 24 bytes · alignof(MyStruct) = 8 bytes · 10 bytes of padding (41.7%)
Frequently Asked Questions
What is struct padding and why does it matter?
Struct padding is extra bytes that compilers insert between struct fields to satisfy alignment requirements. CPUs access memory most efficiently when data is aligned to addresses that are multiples of the data size. For example, a 4-byte int should ideally start at an address divisible by 4. Without proper alignment, some architectures crash and others suffer performance penalties. Understanding padding helps you write cache-friendly, memory-efficient code.
How does memory alignment work in C and C++?
In C and C++, each data type has a natural alignment equal to its size: char aligns to 1 byte, short to 2, int to 4, double to 8, and pointers to 4 or 8 depending on the architecture. The compiler inserts padding bytes before a field if the current offset is not a multiple of that field's alignment. The struct itself is padded at the end so its total size is a multiple of the largest field's alignment.
How is Rust memory layout different from C?
By default, Rust is free to reorder struct fields to minimize padding — the compiler makes no guarantees about field order. If you need C-compatible layout, use #[repr(C)]. This tool supports both modes and also visualizes Rust enums (tagged unions) with discriminant bytes and per-variant payload layout. For Option<&T> and Option<bool>, it shows niche optimization where the compiler avoids a separate discriminant by using invalid bit patterns (like null for references).
Why is my struct larger than the sum of its fields?
The extra bytes are padding. For example, a struct with a char (1 byte) followed by a double (8 bytes) needs 7 bytes of padding between them so the double is aligned to an 8-byte boundary. The struct may also have trailing padding to ensure arrays of the struct maintain alignment. Our visualizer shows every padding byte so you can see exactly where space is wasted.
How can I reduce struct padding and save memory?
The simplest optimization is to order fields from largest alignment to smallest. This tool includes an optimization feature that shows a preview of the reordered layout and the exact byte savings before you apply it. You can also use the step-by-step trace to understand exactly how the compiler places each field and where padding gets inserted. In C, #pragma pack or __attribute__((packed)) can eliminate padding entirely, though this may hurt performance on some architectures.
What does the packed attribute do?
The packed attribute (__attribute__((packed)) in GCC/Clang, #[repr(packed)] in Rust, or #pragma pack in MSVC) tells the compiler to remove all padding between fields and set struct alignment to 1. This produces the smallest possible struct but may cause slower or incorrect memory access on some architectures, since fields may no longer be naturally aligned. Use it when memory savings outweigh performance concerns, such as in network protocols or file formats.
What operating systems and architectures does this tool support?
The tool supports Linux, Windows, macOS, and Bare Metal/Freestanding targets with 7 architectures: x86, x86-64, ARM32, ARM64, AVR, RISC-V 32, and RISC-V 64. Type sizes depend on the OS and compiler — for example, unsigned long is 8 bytes on Linux x86-64 (LP64 data model) but 4 bytes on Windows x86-64 (LLP64). On Windows you can choose between MSVC and MinGW, which differ in their long double handling. AVR models 8-bit microcontrollers where int is 2 bytes, double equals float at 4 bytes, and all alignments are 1.
Can I visualize C/C++ unions?
Yes. Switch to union mode in the toolbar and the visualizer shows all members overlapping at offset 0, with the union sized to the largest member. The byte grid displays each member as a separate row so you can see how they overlap in memory. This is useful for understanding type punning, variant storage, and how unions interact with padding and alignment.
Does this tool support Rust enums?
Yes. Switch to Rust and select enum mode to define variants with different payloads. The visualizer shows the discriminant tag, per-variant field layout within the shared payload area, and total enum size. For two-variant enums like Option<&T> where one variant is a non-null reference, the tool detects niche optimization and shows how the compiler eliminates the discriminant by using null as the None representation.
Why does type size differ between operating systems?
The C standard specifies minimum type sizes but leaves the exact sizes to the implementation. Different operating systems chose different data models: Linux and macOS use LP64 on 64-bit systems (long = 8 bytes), while Windows uses LLP64 (long = 4 bytes). The long double type varies even more — it is 16 bytes on GCC x86-64, 8 bytes on MSVC (same as double), and 4 bytes on AVR (same as float). This tool lets you select the OS, compiler, and architecture to see the exact type sizes for any combination.
Can I compare type sizes across different platforms?
Yes. Click the ABI button in the toolbar (available in C/C++ mode) to open the ABI comparison table. It shows type sizes and alignments across 8 configurations — Linux GCC on x86/x64/ARM64, Windows MSVC and MinGW on x86/x64, macOS Clang on ARM64, and Bare Metal AVR. Types that differ from the majority are highlighted so you can immediately spot platform-specific differences like long, long double, and pointer sizes.
Is my code sent to a server for analysis?
No. The memory layout calculation runs entirely in your browser using JavaScript. Your struct definitions never leave your device. There are no server calls, no uploads, and no data collection. You can verify this by opening your browser's DevTools Network tab.