🔥 Zig Philosophy & Introduction

🎯 What is Zig?

Zig is a general-purpose, low-level programming language designed for robustness, optimal performance, and clarity. Created by Andrew Kelley, Zig offers manual memory control without macros or hidden allocations. It compiles to native code via LLVM, features compile-time code execution (comptime), and seamlessly integrates with C libraries. Zig prioritizes "no hidden control flow" and explicit error handling.

🔬 Core Pillars

  • No hidden allocations: Every allocation is explicit via allocators.
  • Comptime reflection: Generate types/code at compile time.
  • Cross-compilation first-class: Build for any target from one machine.
  • Error as values: No exceptions, explicit error unions.
  • Zero-cost abstractions: High-level syntax with full control.
const std = @import("std"); pub fn main() !void { std.debug.print("⚡ Zig 0.14+ — Safe & Performant!\n", .{}); }

📦 Variables & Primitives

🎯 Variable declaration

var (mutable) and const (immutable). Zig enforces strict typing with inference via '='. Primitives: u8, i32, f64, bool, comptime_int, etc. Integer sizes explicit. Supports sentinel-terminated arrays and pointers.

🏷️ Primitive types

  • u8, u16, u32, u64 – unsigned integers
  • i8..i128 – signed integers
  • f16, f32, f64, f128 – floating point
  • bool, void, type – meta types
  • optional (?T) and error unions
const max_score: u32 = 100; var current_xp: i32 = 2500; current_xp += 500; const pi = 3.14159; // f64 inferred std.debug.print("XP: {}, Max: {}\n", .{current_xp, max_score});

⚙️ Operators & Pointers

🎯 Arithmetic & Bitwise

Zig provides arithmetic: +, -, *, /, % (remainder). Bitwise: &, |, ^, <<, >>. Also @intCast, @ptrCast for safe conversions. Pointers: *T (single item) and [*]T (many). Address-of: &var.

📋 Special operators

  • orelse – default for optionals
  • catch – handle errors
  • try – propagate error
const a: u32 = 64; const b = a >> 2; // 16 const ptr = &a; std.debug.print("Shift: {}, ptr val: {}\n", .{b, ptr.*});

🔀 Control Flow (if/switch)

🎯 If expressions & Switch

if works with booleans, optionals, error unions. Switch exhaustive, supports ranges and tuples. No implicit fallthrough.

const score = 88; if (score >= 90) { std.debug.print("A+ 🚀\n", .{}); } else if (score >= 70) { std.debug.print("Solid B\n", .{}); } else { std.debug.print("Keep grinding\n", .{}); } const grade = switch (score) { 90...100 => "Excellent", 70...89 => "Good", else => "Study", };

🔄 Loops: while & for

🎯 while and for loops

while condition-based; supports continue/break. for iterates over arrays/slices. Inline for for comptime loops.

var i: u32 = 0; while (i < 5) : (i += 1) { std.debug.print("while: {}\n", .{i}); } const items = [_]u8{10, 20, 30}; for (items) |val, idx| { std.debug.print("items[{}] = {}\n", .{idx, val}); }

⚡ Functions & Defer

🎯 Functions as first-class

fn keyword, explicit return type, defer ensures cleanup, errdefer on error path. Supports inline and comptime.

fn add(x: i32, y: i32) i32 { defer std.debug.print("Add complete\n", .{}); return x + y; } pub fn main() void { var file = std.fs.cwd().openFile("test.txt", .{}) catch |err| { std.debug.print("err: {}\n", .{err}); return; }; defer file.close(); _ = add(5, 10); }

📐 Arrays & Slices

🎯 Fixed-size arrays & slices

[N]T compile-time length; []T slice (ptr+len). Slices are bounds-checked by default. Multi-dimensional arrays supported.

const arr: [4]u8 = [4]u8{1,2,3,4}; const slice = arr[1..3]; // [2,3] std.debug.print("slice: {any}\n", .{slice});

🏗️ Structs & Enums

🎯 Structs with methods

Structs group fields, can have decls, methods via 'pub fn'. Enums are explicit with possible payloads. Default field values.

const Player = struct { name: []const u8, hp: u32 = 100, pub fn heal(self: *Player, amount: u32) void { self.hp += amount; } }; const Status = enum { Active, Idle, Dead }; var p = Player{ .name = "ZigCoder" }; p.heal(20); std.debug.print("Player {} HP: {}\n", .{p.name, p.hp});

🛡️ Error Handling (try/catch)

🎯 Error Union (E!T)

Errors are values, defined with error{FileNotFound, AccessDenied}. Use try to bubble, catch to handle, orelse for defaults.

const MyError = error{InvalidData}; fn risky_op(ok: bool) MyError!u32 { if (!ok) return MyError.InvalidData; return 42; } pub fn main() !void { const val = risky_op(true) catch |err| { std.debug.print("Caught: {}\n", .{err}); return; }; std.debug.print("Value: {}\n", .{val}); }

💾 Allocators & Memory

🎯 Explicit Allocators

Zig forces explicit memory management: std.heap.page_allocator, GeneralPurposeAllocator. allocator.alloc(T, n), free with allocator.free.

const alloc = std.heap.page_allocator; var list = try alloc.alloc(u32, 3); defer alloc.free(list); list[0] = 100; list[1] = 200; std.debug.print("allocated list: {any}\n", .{list});

✨ Comptime (Compile-time)

🎯 Compile-time execution

comptime keyword runs code at compilation. Generic programming, type generation, and static evaluation. @typeInfo, @compileLog for reflection.

fn Matrix(comptime T: type, comptime rows: usize, comptime cols: usize) type { return struct { data: [rows][cols]T }; } const Mat3x2 = Matrix(f32, 3, 2); comptime { std.debug.print("Compile-time check: size = {}\n", .{@sizeOf(Mat3x2)}); }

📍 Pointers & Optionals

🎯 Single-item & many-item pointers

*T pointer to one value, [*]T many. Optional ?T can be null, handled with orelse or if unwrap.

var num: i32 = 42; const ptr: *i32 = # ptr.* += 10; var maybe_val: ?u8 = null; if (maybe_val) |v| { std.debug.print("value: {}\n", .{v}); } else { std.debug.print("null handled\n", .{}); }

🔗 Unions & Tagged Unions

🎯 Tagged unions (sum types)

Unions without tag are unsafe; tagged unions (enum + union) provide safe discriminated unions. switch on the tag.

const Value = union(enum) { int: i32, float: f64, text: []const u8, }; var v = Value{ .int = 100 }; switch (v) { .int => |i| std.debug.print("int: {}\n", .{i}), .float => |f| std.debug.print("float: {d}\n", .{f}), .text => |t| std.debug.print("text: {s}\n", .{t}), }

⏩ Async & Build System

🎯 Async functions & cross-compilation

Zig supports async/await for cooperative multitasking (optional). The build system (build.zig) provides declarative cross-compilation, package management, and C integration.

🔧 Modern Zig workflow

  • build.zig – configure exe/lib, targets, modules.
  • zig cc / zig c++ – drop-in C compiler replacement.
  • Zero-dependency cross builds for Windows/Linux/macOS/WASM.
// example build.zig snippet const exe = b.addExecutable(.{ .name = "zigpro", .root_source_file = .{ .path = "src/main.zig" }, .target = b.standardTargetOptions(.{}), }); exe.linkLibC(); b.installArtifact(exe);