Hello World, strings in Zig
I am doing the Exercism exercises for Zig and decided to document my progress since, with every exercise, I learn new and interesting information.
The first exercise is doing a “Hello World” and the end solution is simple:
pub fn hello() []const u8 {
return "Hello, World!";
}
The interesting part is that Zig represents string literals as []const u8
, which is an array of bytes.
const foo = "Hello"
is (almost) the same as const foo = [_]u8{ 'H', 'e', 'l', 'l', 'o' };
Let’s break it down:
const
means it’s a constant value or immutable.[_]u8
means it’s an array of bytes.- The compiler will infer the
[_]
 to[5]
.
Where the string uses double quotes (“H”), and the individual characters (‘H’) use single quotes.
But there is more because a string also contains a sentinel value. A sentinel value is something that indicates the end of a sequence. A popular choice of a sentinel value is the value 0
, also called the null character.
Zig supports sentinel-terminated arrays, slices, and pointers:
//. This is taken from Ziglings, exercise 76.
// const a: [4:0]u32 = [4:0]u32{1, 2, 3, 4};
// const b: [:0]const u32 = &[4:0]u32{1, 2, 3, 4};
Array a
stores five values, the last of which is a 0
. Array b
is only allowed to point to zero-terminated arrays.
Now we can determine the actual type of a string in Zig:
@TypeOf("foo") == *const [3:0]u8
Translated to English, a string is a “constant pointer to a null-terminated fixed-size array of u8”.
Now, why would you still have a 0
at the end when you know the size of the array? That’s because Zig strings are compatible with C strings, which are also null-terminated.
If you want to learn more about strings, I can recommend the Zig / Strings in 5 minutes article.