What Zig 0.17 Means for Systems Programming with Zig

Zig 0.17 was released yesterday, on October 2, 2026. Systems Programming with Zig was written for Zig 0.16, so the first thing I did was to compile all the code of the book with the new version. I wanted to know how much of it breaks before anyone asks me. The short answer is that very little breaks and I have already fixed it.

The numbers Link to heading

The book repository has 152 Zig source files. I had to change 35 of them and the other 117 compile with Zig 0.17 exactly as they are printed in the book. Out of the 35 files, 22 are on the list because of a single change, the removal of @cImport(). If I leave out the comments I added, the whole port is fewer than 60 lines of new code in a repository of about 17,000 lines. Chapter 12, which builds the zcalc interpreter, did not need any changes at all.

Chapter Files changed
1 — Building Essential UNIX Tools 1
2 — Systems Infrastructure 2
3 — Direct Memory Access and Binary Formats 2
4 — Processing Streams, Buffers and Data Encoding 1
5 — Navigating Directories and Filesystem Events 3
6 — Programming the Network Stack 7
7 — Managing Threads, Processes and Signals 7
8 — Orchestrating Concurrency and Synchronization 2
9 — Implementing Asynchronous I/O 2
10 — Building a High-Performance In-Memory Cache Server 2
11 — Persisting Structured Data with SQLite3 6
12 — Developing a Domain Specific Language 0

What did not change Link to heading

Zig 0.16 was the difficult release. It introduced std.Io, the new main() signature with std.process.Init and the new async and await model, and I rewrote a big part of the book because of it while I was still writing it. Zig 0.17 leaves all that alone. Programs still begin with pub fn main(init: std.process.Init) !void, they still get init.io, init.gpa and init.arena and they still read and write through std.Io readers and writers. Threads, mutexes, atomics, sockets, signals, fork(2), kqueue and io_uring work as the book describes them. The same goes for the things that have nothing to do with a Zig version, like how a Zip file is laid out on disk, why buffering saves system calls or how to design a binary protocol for a cache server.

What changed Link to heading

The biggest change is that @cImport() is gone. The programs that include C header files now use the zig translate-c command and a regular @import(). It is a one line change per program and I wrote a separate post about it, @cImport() Is gone in Zig 0.17, using a program from Chapter 1. The rest of the changes are small and mechanical. The ** operator for repeating arrays was removed, so six lines now use @splat():

// Zig 0.16
var table: [256]u8 = [_]u8{0xFF} ** 256;

// Zig 0.17
var table: [256]u8 = @splat(0xFF);

The build.zig files that pass command line arguments to zig build run got one line shorter:

// Zig 0.16
if (b.args) |args| run_cmd.addArgs(args);

// Zig 0.17
run_cmd.addPassthruArgs();

Two functions were renamed. allocator.dupeZ(u8, s) is now allocator.dupeSentinel(u8, s, 0) and std.fmt.bufPrintZ() is now std.fmt.bufPrintSentinel(), each used once in the book. Last, @typeInfo() returns the fields of a struct as two separate lists, field_names and field_types, instead of one fields list. This affects the comptime code of Chapters 3, 6, 7 and 11, a handful of lines in total.

Using the book with Zig 0.17 Link to heading

The GitHub repository at https://github.com/mactsouk/zigSP has both versions. The main branch has the code for Zig 0.17 and the 0.16 branch has the code as it is printed in the book. In the main branch, every line that I changed has a comment above it that shows the old version of the line:

// Zig 0.16: var table: [256]u8 = [_]u8{0xFF} ** 256;
var table: [256]u8 = @splat(0xFF);

So when a listing on the page is different from the file you have open, the comment shows you the line as it is in the book and the line below it is what Zig 0.17 wants. If you prefer to follow the book exactly as printed, Zig 0.16 is still available from the Zig download page and the 0.16 branch works with it.

Deprecated, not broken Link to heading

Zig 0.17 also deprecated some names without removing them. std.heap.DebugAllocator is one of them, with std.heap.SafeAllocator as its replacement. The book uses DebugAllocator in a few chapters and that code still compiles and runs with Zig 0.17. I will move these to the new names in the repository before the next Zig release removes the old ones.

Should you still buy the book? Link to heading

I am the author, so you know what I am going to say. But I did not have to guess. I compiled every program in the repository with Zig 0.17 and ran the tests of the projects that have them. Zig has not reached version 1.0 yet and every Zig book will go through this with every new release. What matters is how big the gap is and whether someone keeps the code working. This time the gap is 35 files with small edits and the code is already updated. I plan to do the same for the next release.

You can buy the book from Amazon.com or from Packt Publishing.

Happy coding in Zig!