str
The str type (pronounced "string slice") is a primitive, unsized (!Sized), UTF-8 encoded sequence of bytes, almost always accessed behind a borrowed reference as &str (or &mut str, Box<str>, Arc<str>).
Memory Layout of &str
Because str is a Dynamically Sized Type ([u8] guaranteed to be valid UTF-8), a reference &str is a 16-byte fat pointer on 64-bit platforms consisting of a pointer to the first byte and a byte length:
Stack (`&str`, 16 bytes) Read-Only Binary Data / Heap / Stack
+----------------+ +---+---+---+---+---+---+---+---+---+
| ptr (8 B) +-----------------> | r | u | s | t | - | l | a | n | g |
| len = 4 | +---+---+---+---+---+---+---+---+---+
+----------------+ └───┬───┘
4-byte slice "rust"
Unlike String, &str has no capacity field because it does not own a growable allocation—it is a fixed-length view into UTF-8 bytes stored somewhere in memory.
Where the Bytes Behind a &str Can Live
A &str can borrow UTF-8 text from any memory region:
- Static read-only binary data (
&'static str): String literals such as"hello"are baked directly into the compiled executable's read-only data segment and have type&'static str. - A heap-allocated
String: Borrowing&my_stringor&my_string[0..4]creates a&strpointing intomy_string's heap buffer. - A stack buffer: Validating a stack byte array
[u8; N]viastd::str::from_utf8(&buf)returns a&strpointing into the stack frame.
fn describe_slice(label: &str, text: &str) {
println!(
"{label:<14} -> '{text}' (len = {} bytes, ptr = {:p})",
text.len(),
text.as_ptr()
);
}
fn main() {
// 1. Static literal in binary read-only memory:
let literal: &'static str = "static_literal";
// 2. Slice into a heap-allocated `String`:
let heap_string = String::from("heap_allocated_text");
let heap_slice: &str = &heap_string[0..4];
// 3. Slice into a stack byte array validated as UTF-8:
let stack_bytes: [u8; 5] = *b"stack";
let stack_slice: &str = std::str::from_utf8(&stack_bytes).unwrap();
describe_slice("Literal", literal);
describe_slice("Heap slice", heap_slice);
describe_slice("Stack slice", stack_slice);
}
Literal -> 'static_literal' (len = 14 bytes, ptr = 0x104a1c000)
Heap slice -> 'heap' (len = 4 bytes, ptr = 0x600001714020)
Stack slice -> 'stack' (len = 5 bytes, ptr = 0x16b3ef4eb)
Immutable Heap String Slices (Box<str> and Arc<str>)
When an owned string will never grow or shrink after creation, converting a String into Box<str> (via string.into_boxed_str()) or Arc<str> drops the excess capacity and shrinks the handle from 24 bytes (ptr, len, capacity) to 16 bytes (ptr, len), saving 8 bytes per string in large symbol tables or AST nodes.