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.

5 Likes

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

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.