Zig In-Depth Overview

andrewstetsenko1 pts0 comments

Overview<br>Zig Programming Language

Download

Learn

News

Source<br>Join a Community

Zig Software Foundation

Devlog

← Back to<br>Learn

Overview

Feature Highlights<br>Small, simple language<br>Focus on debugging your application rather than debugging your programming language knowledge.<br>Zig’s entire syntax is specified with a 580-line PEG grammar file.<br>There is no hidden control flow , no hidden memory allocations, no preprocessor, and no macros. If Zig code doesn’t look like it’s jumping away to call a function, then it isn’t. This means you can be sure that the following code calls only foo() and then bar(), and this is guaranteed without needing to know the types of anything:<br>var a = b + c.d;<br>foo();<br>bar();

Examples of hidden control flow:<br>D has @property functions, which are methods that you call with what looks like field access, so in the above example, c.d might call a function.<br>C++, D, and Rust have operator overloading, so the + operator might call a function.<br>C++, D, and Go have throw/catch exceptions, so foo() might throw an exception, and prevent bar() from being called.<br>Zig promotes code maintenance and readability by making all control flow managed exclusively with language keywords and function calls.<br>Performance and Safety: Choose Two<br>Zig has four build modes, and they can all be mixed and matched all the way down to scope granularity.<br>ParameterDebugReleaseSafeReleaseFastReleaseSmallOptimizations - improve speed, harm debugging, harm compile timeOnOnOnRuntime Safety Checks - harm speed, harm size, crash instead of undefined behaviorOnOnHere is what Integer Overflow looks like at compile time, regardless of the build mode:<br>1-integer-overflow.zigtest "integer overflow at compile time" {<br>const x: u8 = 255;<br>_ = x + 1;<br>}Shell$ zig test 1-integer-overflow.zig<br>/home/ci/.cache/act/88f43fa1ec284c64/hostexecutor/zig-code/features/1-integer-overflow.zig:3:11: error: overflow of integer type 'u8' with value '256'<br>_ = x + 1;<br>~~^~~

Here is what it looks like at runtime, in safety-checked builds:<br>2-integer-overflow-runtime.zigtest "integer overflow at runtime" {<br>var x: u8 = 255;<br>x += 1;<br>}Shell$ zig test 2-integer-overflow-runtime.zig<br>1/1 2-integer-overflow-runtime.test.integer overflow at runtime...thread 3534273 panic: integer overflow<br>/home/ci/.cache/act/88f43fa1ec284c64/hostexecutor/zig-code/features/2-integer-overflow-runtime.zig:3:7: 0x1238175 in test.integer overflow at runtime (2-integer-overflow-runtime.zig)<br>x += 1;<br>/home/ci/deps/zig-x86_64-linux-0.16.0/lib/compiler/test_runner.zig:291:25: 0x11f35c6 in mainTerminal (test_runner.zig)<br>if (test_fn.func()) |_| {<br>/home/ci/deps/zig-x86_64-linux-0.16.0/lib/compiler/test_runner.zig:73:28: 0x11f2de2 in main (test_runner.zig)<br>return mainTerminal(init);<br>/home/ci/deps/zig-x86_64-linux-0.16.0/lib/std/start.zig:699:88: 0x11ef5f5 in callMain (std.zig)<br>if (fn_info.params[0].type.? == std.process.Init.Minimal) return wrapMain(root.main(.{<br>/home/ci/deps/zig-x86_64-linux-0.16.0/lib/std/start.zig:190:5: 0x11eefd1 in _start (std.zig)<br>asm volatile (switch (native_arch) {<br>error: the following test command terminated with signal ABRT:<br>/home/ci/.cache/act/88f43fa1ec284c64/hostexecutor/.zig-cache/o/1754ade03a859de2f0c6722488dc6ee4/test --seed=0xd0d60372

Those stack traces work on all targets, including freestanding.<br>With Zig one can rely on a safety-enabled build mode, and selectively disable safety at the performance bottlenecks. For example the previous example could be modified like this:<br>3-undefined-behavior.zigtest "actually undefined behavior" {<br>@setRuntimeSafety(false);<br>var x: u8 = 255;<br>x += 1; // XXX undefined behavior!<br>Zig uses Illegal Behavior as a razor sharp tool for both bug prevention and performance enhancement.<br>Speaking of performance, Zig is faster than C.<br>All Zig code lives in one compilation unit, optimized together.<br>Carefully chosen illegal behavior. For example, in Zig both signed and unsigned integers have illegal behavior on overflow, contrasted to only signed integers in C. This facilitates optimizations that are not available in C.<br>Zig directly exposes a SIMD vector type, making it easy to write portable vectorized code.<br>The standard library provides essential data structures such as hash maps and array lists, whereas in C it is tempting to use linked lists for simplicity.<br>Advanced CPU features are enabled by default, unless cross-compiling.<br>Zig competes with C instead of depending on it<br>The Zig Standard Library integrates with libc, but does not depend on it. Here’s Hello World:<br>4-hello.zigconst std = @import("std");

pub fn main() void {<br>std.debug.print("Hello, world!\n", .{});<br>}Shell$ zig build-exe 4-hello.zig<br>$ ./4-hello<br>Hello, world!

When compiled with -O ReleaseSmall, debug symbols stripped, single-threaded mode, this produces a 9.8 KiB static executable for the x86_64-linux target:<br>$ zig build-exe hello.zig -O ReleaseSmall -fstrip -fsingle-threaded<br>$ wc -c hello<br>9944 hello<br>$ ldd hello<br>not a dynamic executable<br>A Windows build is even smaller,...

overflow integer hello runtime code home

Related Articles