What's difference between &str and string slice?

fn main() {
    let s = String::from("hello world");

    let m = "hello world";

    let _s = &s;
    let a = &s[0..5];
    let b = &s[6..11];
}

In this code, I have defined some variables and they have different types. s is of String type, _s is of &String type, m, a, and b are all of &str type. So I'm confused what is the difference between m and a and b? If a and b are both structs, containing a pointer and a length, then is m also the same struct? In other words, str is the string itself. Are all uses of strings in the rust language through pointers?


Your understanding is correct. m, a and b are all of type &str. They are all references to string slices.

You can't have a variable of type str because str is a dynamically sized type. Rust has no support for storing dynamically sized types in variables, hence all operations on such types have to be done indirectly via some sort of pointers.

5 Likes

First, I modified the example code like so:

fn main() {
    let s = String::from("hello world");
    let m = "hello world";

    let _s = &s;
    let a = &s[0..5];
    let b = &s[6..11];

    println!("&s:\t{:016p}: {}", &s, bytes_of(&s));
    println!("&m:\t{:016p}: {}", &m, bytes_of(&m));
    println!("&_s:\t{:016p}: {}", &_s, bytes_of(&_s));
    println!("&a:\t{:016p}: {}", &a, bytes_of(&a));
    println!("&b:\t{:016p}: {}", &b, bytes_of(&b));
}

fn bytes_of<T>(v: &T) -> String {
    let bytes;
    unsafe {
        let ptr = v as *const T as *const u8;
        let len = std::mem::size_of::<T>();
        bytes = std::slice::from_raw_parts(ptr, len);
    }

    let mut s = String::new();
    use std::fmt::Write;

    write!(&mut s, "[").unwrap();
    for (i, byte) in bytes.iter().copied().enumerate() {
        if i > 0 { write!(&mut s, ",").unwrap(); }
        write!(&mut s, "{byte:02x}").unwrap();
    }
    write!(&mut s, "]").unwrap();

    s
}

I then ran this and used the output to construct the following diagram:

Screenshot of a memory layout diagram done using a spreadsheet.  A link to the original is below.

You can also view this diagram as the original spreadsheet if you want.

Each column is a single byte in memory, and this is using the real addresses from my machine. The coloured lines represent pointers and references (I use v and ^ to indicate the direction of the pointer).

Note that you will probably not have the same addresses on your machine, and their layout might change.

Hope this helps solidify your understanding.

4 Likes

I successfully ran your program and I've seen the list of output. Thank you very much!