[Avg. reading time: 3 minutes]

Owner Borrower Stack Heap

fn main() {
    let o = String::from("Rachel Green");

    println!("o (String owner): {o}");
    println!("o.len (bytes): {}", o.len());
    println!("o.capacity (bytes): {}", o.capacity());

    // stack vs heap
    println!("\nstack addr of o (String struct): {:p}", &o);
    println!("heap ptr held by o:            {:p}", o.as_ptr());

    // slice: &str borrows part of o (points into the same heap buffer)
    let s: &str = &o[7..]; // "Green" for ASCII input
    println!("\ns (&str slice): {s}");
    println!("stack addr of s (&str ref):    {:p}", &s);
    println!("ptr of s (into o's buffer):    {:p}", s.as_ptr());

    // borrow: &String (borrow the whole String)
    let b: &String = &o;
    println!("\nb (&String borrow): {b}");
    println!("stack addr of b (&String ref): {:p}", &b);
    println!("b points to String struct o:    {:p}", b as *const String);
    println!("b -> heap ptr:                 {:p}", b.as_ptr());

    // Key takeaway
    println!("\nCheck: o.as_ptr == s.as_ptr ?  {}", o.as_ptr() == s.as_ptr());
    println!("Check: o.as_ptr == b.as_ptr ?  {}", o.as_ptr() == b.as_ptr());

    let moved = o;
    // println!("{}", o); // error: moved
    println!("{}", moved);

}

#owner #borrower #stack #heapVer 2.0.12

Last change: 2026-02-18