Does slice have extra dynamic data?

Have a question: does the slice have any extra data for example zero at the end of the string or size of the string at the beginning of the string?

In this code:

use std::collections::HashMap;

fn main()
{
  let mut hashmap : HashMap< &'static str, &'static str > = HashMap::new();
  hashmap.insert( "EUR", "Euro" );
  hashmap.insert( "USD", "US Dollar" );
  hashmap.insert( "CHF", "Swiss Francs" );

  let usd = hashmap.get( "EUR" );
  if let Some( usd ) = usd
  {
    println!( "usd : {}", usd );
  }
  // < usd : Euro
}

Key as well as the value of the HashMap let mut hashmap : HashMap< &'static str, &'static str > could have any length. Right? I don't understand how does the program knows usd has length/size of 4? Does the slice have any extra data for example zero at the end of the string or size of the string at the beginning of the string?

Playground is here.

Both approach can't support subslicing without allocation. So we store the length next to the ptr as a part of the reference. Sometimes people call it fat pointer.

3 Likes

Slice types such as str or [u8] are called unsized types, which means that they can have many different sizes, as you have noticed yourself. Whenever you have any kind of reference or pointer to an unsized type, the reference itself will include some extra information that lets you determine the length as part of the reference itself. You should think of a &str as the following struct:

struct &str {
    first_elem: &u8,
    length: usize,
}

Of course this is made up syntax and it is not defined with an actual struct.

To illustrate the difference, try computing the size of references to sized and unsized types:

use std::mem::size_of;

fn main() {
    println!("Size of &u32 is {}", size_of::<&u32>());
    println!("Size of &str is {}", size_of::<&str>());
}
Size of &u32 is 8
Size of &str is 16

The &str is larger because it has both a pointer and a length.

This design is also why subslicing works. If you included the length at the start or a null byte at the end, then you couldn't implement &my_str[4..7] because it would have to modify the string it points at.

4 Likes

Aha! It makes sense. Thank you :heart:

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.