[Avg. reading time: 11 minutes]
Memory Layout
How many bytes does a type actually occupy?
The std::mem::size_of::
use std::mem; fn main() { println!("i32 : {}", mem::size_of::<i32>()); println!("u32 : {}", mem::size_of::<u32>()); println!("f64 : {}", mem::size_of::<f64>()); println!("char : {}", mem::size_of::<char>()); println!("&str : {}", mem::size_of::<&str>()); println!("String : {}", mem::size_of::<String>()); }
| Type | Size (bytes) | Why |
|---|---|---|
i32 | 4 | 32 bits = 4 bytes |
u32 | 4 | 32 bits unsigned |
f64 | 8 | 64-bit float |
char | 4 | Unicode scalar value |
&str | 16 | pointer (8) + length (8) |
String | 24 | pointer (8) + length (8) + capacity (8) |
| Type | Stack Size | Heap Usage |
|---|---|---|
i32 | 4 | None |
f64 | 8 | None |
char | 4 | None |
&str | 16 | No Ownership |
String | 24 | Yes, for text |
- Primitive numeric types store values directly.
- &str is a pointer containing a memory address and length.
- String stores metadata on the stack but allocates its text on the heap.
String Literal points to location where Literal values are stored (Static Memory).
fn main(){ let s = "Rachel"; println!("{},{:p}", s, s.as_ptr()) }
Memory Alignment

CPUs generally do not read memory one byte at a time. Instead, they read in “words” (e.g., 8 bytes on a 64-bit system). If a multi-byte value is “misaligned”—meaning it straddles the boundary between two words—the CPU might have to perform two memory accesses instead of one, or in some architectures, it may trigger a hardware exception and crash.
use std::mem; fn main() { let a: i32 = 42; let b: char = 'R'; let c: String = String::from("Rachel"); println!("Sizes and Alignments"); println!("i32 -> size: {}, align: {}", mem::size_of::<i32>(), mem::align_of::<i32>()); println!("char -> size: {}, align: {}", mem::size_of::<char>(), mem::align_of::<char>()); println!("String -> size: {}, align: {}", mem::size_of::<String>(), mem::align_of::<String>()); println!("\nStack Addresses"); println!("a (i32) at {:p}", &a); println!("b (char) at {:p}", &b); println!("c (String) at {:p}", &c); println!("\nHeap Address (String data)"); println!("c text buffer at {:p}", c.as_ptr()); }
Padding & Memory Alignment
Padding: If you have a 1-byte variable followed by an 8-byte variable, the CPU can’t fit the big one into the remaining 7 bytes of its current “gulp” without splitting it. To avoid this, the computer leaves those 7 bytes empty. That empty space is padding.
Alignment: This is the rule that says data must be placed exactly where the CPU’s “gulp” starts. If you want an 8-byte integer, it needs to be perfectly lined up with the straw.
- A value must start at a memory address that is a multiple of its alignment.
- Alignment is determined by the type.
On a 64-bit system:
-
i32 Size = 4 bytes | Alignment = 4 bytes
-
u64, usize, String, pointers Size = 8 bytes (or more for String) | Alignment = 8 bytes
Example:
- Bikes (1-byte) can park in any 1-foot slot.
- Cars (4-bytes) must park in slots that are multiples of 4 (Slot 0, 4, 8…).
- Buses (8-bytes) must park in slots that are multiples of 8 (Slot 0, 8, 16…).
Memory App Analyzer
Sometimes it takes time to start the app, please wait.