Difference between &[u8;3] and *const u8?

Hi,
I'm wondering what's the difference between
let a = b"123\0";
and
let b = b"123\0".as_ptr()
Originally I thought one is a slice (a) which includes both length and pointer and one is just a pointer (b).
But in practice when I pass both options to an unsafe c function that prints a null terminated string they both work the same. Also running std::mem::size_of::<&[u8;3]>() and std::mem::size_of::<*const u8>() both return 8, so they both only contain a pointer and not a size. How can this be?

The only difference is in what the compiler allows you to do with the value: access to &[u8;3] (from Rust code) will produce a compile error if the backing data has been deallocated and a runtime panic if indexed outside the range 0..3.

The *const u8 bypasses all of these checks, so misuse can potentially read uninitialized or sensitive data, potentially causing undesired behavior like security leaks or program crashes.

2 Likes

So is it true to say that rust slices are compile time creatures, and that a slice variable's "length" is fixed?

Not quite. &[u8;3] is a reference to an array, and Rust arrays are always fixed-length (known at compile-time).

&[u8] is a reference to a slice; it carries runtime length information alongside the pointer to its contents. This lets it be different lengths during different runs of the same program.

3 Likes

std::mem::size_of::<&[u8]>() really returns 16.
Thanks that explains it.
Although I'm still a bit surprised a reference to something can have different sizes. What I mean is that a reference to a slice has a different size than a reference to an array or just a plain unsafe pointer.

Within your program, all accesses to the array will be checked at compile-time, i.e. there's no need to keep the information of the length at runtime.

Yes, that’s right. The other case when the reference can be a “fat pointer” is when it is a reference to a trait object, in that case rather than a length, the second half of the fat pointer is a second pointer to a vtable for looking up methods.

https://doc.rust-lang.org/reference/dynamically-sized-types.html

4 Likes

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.