Zig Language Overview

Zig 0.14 — systems language | no hidden control flow | no hidden allocations | no preprocessor | compile-time execution

Paradigm

Imperative, procedural, data-oriented. Static typing with inference, structural (duck) typing via comptime. Compilation via LLVM + self-hosted backend. No operator overloading, no exceptions, no RAII, no macros.

Types

Category Types
Signed int i8 i16 i32 i64 i128 isize
Unsigned int u8 u16 u32 u64 u128 usize
Float f16 f32 f64 f128
Bool bool
Void void
Never noreturn
Array [N]T
Slice []T
Pointer *T *const T [*]T (many-item) [*c]T (C pointer)
Optional ?T
Error union E!T
Struct struct { field: T }
Union union { field: T } (tagged)
Enum enum { variant }
Packed union/enum packed union packed enum
Vector @Vector(N, T) (SIMD)
Function fn(params) ReturnType
Opaque opaque {}
Comptime comptime T (compile-time known)
Any type anytype (comptime duck typing)
Any error anyerror
Type type (first-class type)
Void (zero bits) comptime void

Declarations

Construct Syntax Notes
Function fn name(params) ReturnType { body }
Variable const x = expr; Immutable
Mutable var x = expr;
Constant const NAME: T = expr; Known at comptime
Export export fn name() void { ... } Visible to linker
Extern extern fn name() void; From another object
Struct const T = struct { field: T };
Enum const E = enum { variant };
Union const U = union(enum) { field: T }; Tagged union
Error set const Errors = error { E1, E2 };
Test test "name" { ... }
Comptime block comptime { ... }
Inline assembly asm volatile ("code");
Import const std = @import("std");

Control Flow

Construct Syntax Notes
If if (cond) { ... } else { ... }
If (expression) const x = if (cond) a else b;
If (optional) if (opt) |val| { ... } else { ... } Capture unwrap
If (error union) if (result) |val| { ... } else |err| { ... }
While while (cond) { ... }
While (optional) while (opt) |val| { ... }
While (error) while (result) |val| { ... } else |err| { ... }
For for (slice) |item| { ... }
For (index) for (slice, 0..) |item, i| { ... }
Switch switch (expr) { variant => body, else => body } Exhaustive
Break break;
Continue continue;
Return return expr;
Defer defer expr; Run at scope exit
Errdefer errdefer expr; Run on error
Catch result catch |err| { ... } Unwrap or handle

Switch Features

Operators

Category Operators
Arithmetic + - * / %
Wrapping +% -% *%
Saturation +| -| *|
Comparison == != < > <= >=
Logical and or !
Bitwise >> << & | ^ ~
Compound += -= *= /%= &= |= ^= <<= >>=
Nullable orelse catch .? (optional unwrap)
Misc .. (range) ** (ptr deref multi) . (field) .* (ptr deref)
Address-of &expr

Comptime (Metaprogramming)

fn max(comptime T: type, a: T, b: T) T {
    return if (a > b) a else b;
}

comptime {
    // Runs at compile time
    @compileLog("building for", @tagName(builtin.cpu));
}

// Generics via comptime parameters
fn ArrayList(comptime T: type) type {
    return struct {
        items: []T,
        fn init(self: *Self) void { ... }
    };
}

Comptime Features

Memory

Operation Syntax Notes
Allocate allocator.alloc(T, n) Returns ![]T
Free allocator.free(slice)
Realloc allocator.realloc(slice, n)
Create allocator.create(T) Single element
Destroy allocator.destroy(ptr)
Allocator param allocator: Allocator Always explicit

Allocators

std.heap.page_allocator std.heap.arena_allocator std.heap.FixedBufferAllocator std.heap.ArenaAllocator std.heap.StackFallbackAllocator std.heap.c_allocator

Zig's allocator philosophy

Error Handling

// Error union type: ReturnType!Error
fn div(a: i32, b: i32) !i32 {
    if (b == 0) return error.DivisionByZero;
    return a / b;
}

// Try operator: early return on error
const result = try div(10, 2);

// Catch: provide default
const val = div(10, 0) catch 0;

// Global error set vs specific
fn parse() ParseError!i32 { ... }

Defer & Errdefer

{
    const buf = try allocator.alloc(u8, 100);
    defer allocator.free(buf);  // always runs at scope exit
    errdefer allocator.free(buf);  // runs only if error returned

    // ... use buf
}  // defer triggers here

Standard Library (selected)

Module Contents
std.fs File, Dir, Path, cwd, readFile, writeFile, copyFile, deleteFile, makeDir, makePath
std.io Reader, Writer, Buffered, formatting, printing
std.net TcpStream, TcpListener, UdpSocket, IpAddress, dns
std.mem copy, set, swap, indexOf, split, join, Allocator, Allocator interface
std.process ChildProcess, Args, Env, exit, getSelfPath
std.time Instant, nanoTime, sleep, Timer, epoch
std.Thread spawn, Pool, Mutex, RwLock, Semaphore, Condition, Atomic
std.math sqrt, sin, cos, tan, exp, log, pow, abs, min, max, clamp
std.hash hash functions, crc32, sha256, sha512, md5
std.json parse, stringify, Value, Array, Object
std.sort sort, binarySearch, insertion, merge, pdqsort
std.unicode utf8, utf16, width, case mapping
std.Build Build system (replaces make/cmake)
std.Target Cross-compilation target detection
std.debug assert, panic, print, dump, trace

Testing

test "basic addition" {
    try std.testing.expectEqual(4, add(2, 2));
    try std.testing.expect(add(1, 1) == 2);
    try std.testing.expectError(error.DivisionByZero, div(1, 0));
}
zig test file.zig        # run tests
zig build test           # run all tests in project
zig test --name "filter" # filter test names

Cross-Compilation

zig build-exe main.zig --target x86_64-windows  # cross-compile to Windows
zig build-exe main.zig --target aarch64-linux    # cross-compile to ARM64 Linux
zig build-exe main.zig --target riscv64-linux    # cross-compile to RISC-V

Zig ships with libc headers and cross-compilation toolchains for all major targets — no separate cross-compiler needed.

C Interop

// Import C header
const c = @cImport({
    @cInclude("stdio.h");
});

// Link C library
pub fn main() void {
    _ = c.printf("hello %d\n", 42);
}

// Direct use of C ABI
extern "c" fn strlen(s: [*:0]u8) usize;

// Zig is a better C:
// - @cImport for headers
// - export fn for C-ABI exports
// - [*:0]T for null-terminated strings
// - @ptrCast for pointer conversion
// - packed struct for ABI-compatible layouts

Notable differences from C

Compilation

zig build-exe main.zig     # compile executable
zig build-lib lib.zig       # compile library
zig build-obj obj.zig       # compile object
zig run main.zig            # compile + run
zig test file.zig           # compile + run tests
zig fmt file.zig            # format code
zig build                   # build project (build.zig)
zig translate-c foo.h       # translate C header to Zig

Build Modes

Mode Flag Safety checks Optimizations
Debug (default) Full None
ReleaseSafe -Doptimize=ReleaseSafe Full Speed
ReleaseFast -Doptimize=ReleaseFast None Speed
ReleaseSmall -Doptimize=ReleaseSmall None Size