Every value in Rust has exactly one owner, and its type decides where its bytes actually live.
A i32 is 4 bytes and lives entirely in the stack frame of the function that holds it. A String is different: the handle lives on the stack and is always the same size, while the characters live on the heap.
That handle is three words — a pointer, a length, and a capacity:
let name = String::from("stellar");
// stack: [ ptr | len: 7 | cap: 7 ] = 24 bytes on a 64-bit target
// heap: s t e l l a r = 7 bytes
