Perfectly correct, and for posterity, I’ll add that this is not the answer to the title of this question.
Any comptime-known string value is put in .rodata
, static memory, and can’t be altered at runtime. It technically isn’t a slice, either: if the literal string format is used, it’s a zero-terminated sentinel array of u8
.
/// The type of this is [7:0]const u8
const rodata_string = ".rodata";
The example given in the question uses literal array syntax, so it would be a [4]const u8
, without the null terminator. The distinction mainly makes a difference for C interop, if a string is heading to C-land, it’s often important that it be null terminated. A practical, if minor difference, is that it’s legal to read the sentinel, which is at a_string[a_string.len]
, which is one past the end of a normal array (and slice).
These can both be cast to a []const u8
fairly easily, for instance, by passing it to a function which expects one. But they’re of a different type: both the length of an array, and any sentinel terminator it has, are part of the type of that data. Any comptime-known value like this is in static memory and has the length as part of the type. u8
isn’t special here, except that when literal string syntax is used, it automatically becomes a null-sentinel array.
A slice is a pointer and a length, so “where is the memory” is actually two questions: where is the struct with the pointer and the length, and where is the memory that the pointer points at? The answer is not more specific than “wherever the memory is” in either case. The data in a []const u8
can be on the stack, the heap, or in static memory (the last happens when a string literal is cast to a slice), and this is true of the slice itself as well.
Edit: one final point: Arrays aren’t automatically in static memory either. They can be declared on the stack, or allocated on the heap, but the length (and the value of the sentinel when there is one) must be comptime-known. If the data in the array is also comptime-known, then it goes in .rodata
.