Zig DISCUSSION

Zig string literals: why is the type *const [5:0]u8 and how do I store a list of strings?

Started by ksravankumarreddy Zig stringsstring literal typeslicesconst u8sentinel-terminated arrays
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

Zig string literals: why is the type *const [5:0]u8 and how do I store a list of strings?

ksravankumarreddy Zig Forum
#1

I am learning Zig and the string types confuse me. @TypeOf("hello") prints *const [5:0]u8, functions in the standard library take []const u8, and C functions want [*:0]const u8. When I tried to build a table of command names with const names = [_][]u8{ "adc", "uart", "spi" }; the compiler rejected it until I added const in the middle.

What do these types actually mean, why is the const required, and what should my own functions accept?

Community replies 5

Re: Zig string literals: why is the type *const [5:0]u8 and how do I store a list of strings?

#2

A string literal is a pointer to a constant array of bytes stored in the program's read-only data. For "hello" the array type is [5:0]u8: five bytes followed by a 0 sentinel, so 6 bytes are stored but .len is 5. The pointer type *const [5:0]u8 carries the length in the type, which is why literals of different lengths have different types.

It coerces automatically to []const u8 (a slice: pointer plus length), to [:0]const u8 and to [*:0]const u8 (a C-style pointer to a 0-terminated string).

Re: Zig string literals: why is the type *const [5:0]u8 and how do I store a list of strings?

#3

The const is about the bytes, not the variable. []u8 is a slice whose bytes may be written, and a literal lives in read-only memory, so the coercion is refused. [_][]const u8{ "adc", "uart", "spi" } reads as: an array, length inferred, of slices of constant bytes.

The slice element type is also what lets strings of lengths 3, 4 and 3 share one array, since each element is just a pointer and a length, 16 bytes on a 64-bit target, whatever the text it points to.

Re: Zig string literals: why is the type *const [5:0]u8 and how do I store a list of strings?

#4

For parameters, take []const u8 unless you need to modify the bytes or need the terminator. It accepts literals, slices of stack buffers and heap strings alike.

If you need a mutable string, copy the literal into an array of your own: var buf = "hello".*; dereferences the literal and gives you a separate array that you can change (buf[0] = 'J';) and pass on as &buf.

Re: Zig string literals: why is the type *const [5:0]u8 and how do I store a list of strings?

#5

When calling C, a literal can be passed directly to a [*:0]const u8 parameter, the equivalent of const char *. A runtime []const u8 cannot, because nothing guarantees a 0 after its last byte; you need a [:0]const u8, or you must copy the text into a buffer and add the terminator yourself.

Going the other way, std.mem.span(c_ptr) scans for the terminator and returns a slice with a proper length, which the rest of your Zig code can use normally.

Re: Zig string literals: why is the type *const [5:0]u8 and how do I store a list of strings?

#6

Two things surprise people coming from other languages. Strings are plain bytes, normally UTF-8, so .len counts bytes: "10 µF".len is 6, not 5, because µ takes two bytes. And == does not compare contents; use std.mem.eql(u8, a, b).

Concatenation with ++ only works on values known at compile time. At run time, format into a buffer, for example std.fmt.bufPrint(&buf, "{s}-{d}", .{ name, n }), which returns the slice that was written, or an error if the buffer is too small.

TEP COMMUNITY