Introduction to Zig

Welcome to your first lesson in Zig programming! In this introduction, we'll cover what Zig is, why it's unique, and what makes it an excellent choice for systems programming.

What is Zig?

Zig is a general-purpose programming language designed for robustness, optimality, and clarity. Created by Andrew Kelley in 2015, Zig aims to be a better C, providing modern features while maintaining the simplicity and performance that systems programmers need.

What You'll Learn

  • What makes Zig different from other programming languages
  • Zig's core philosophy and design principles
  • How to write your first Zig program
  • Why Zig is great for systems programming

Key Features

Simple and Explicit

Zig has no hidden control flow, no hidden memory allocations, and no preprocessor. What you see is what you get:

const std = @import("std");

pub fn main() !void {
    // Print to stdout
    const stdout = std.io.getStdOut().writer();
    try stdout.print("Hello, Zig!\n", .{});
}

Memory Safety Without Garbage Collection

Zig provides memory safety through compile-time checks and clear ownership, without the runtime overhead of a garbage collector:

const std = @import("std");

pub fn main() !void {
    // Manual memory management with allocators
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // Allocate memory
    const message = try allocator.alloc(u8, 100);
    defer allocator.free(message); // Explicit cleanup

    std.debug.print("Memory allocated!\n", .{});
}

Compile-Time Code Execution

One of Zig's most powerful features is comptime - the ability to run code at compile time:

fn fibonacci(comptime n: u32) u32 {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

pub fn main() !void {
    // This calculation happens at compile time!
    const fib_10 = fibonacci(10);
    std.debug.print("10th Fibonacci number: {}\n", .{fib_10});
}

Why Learn Zig?

  1. Performance: Zero-cost abstractions with C-level performance
  2. Safety: Catch bugs at compile-time without runtime overhead
  3. Simplicity: No hidden control flow or allocations
  4. Interoperability: Seamless C integration without bindings
  5. Modern Tooling: Built-in build system and package manager

Try It Yourself

Let's write your first Zig program! This example demonstrates basic syntax and output:

const std = @import("std");

pub fn main() !void {
    // Variables in Zig
    const language = "Zig";
    const year: i32 = 2024;

    // Print to debug output (easier than stdout for simple examples)
    std.debug.print("Learning {s} in {}!\n", .{language, year});

    // Basic arithmetic
    const a: i32 = 10;
    const b: i32 = 20;
    std.debug.print("{} + {} = {}\n", .{a, b, a + b});

    // Arrays
    const numbers = [_]i32{1, 2, 3, 4, 5};
    std.debug.print("First number: {}\n", .{numbers[0]});
    std.debug.print("Array length: {}\n", .{numbers.len});
}

Try these exercises:

  1. Change the language variable to your favorite programming language
  2. Add a new variable for your name and print it
  3. Create a new array with different numbers
  4. Calculate and print the sum of two numbers

Pro Tip: The best way to learn Zig is by practicing. Try modifying the code examples above and experiment with them in the playground. Don't worry about making mistakes - that's how you learn!

Key Takeaways

  • Zig is a modern systems programming language focused on simplicity and safety
  • It provides manual memory management without garbage collection overhead
  • The comptime feature allows code execution at compile time
  • Zig uses explicit error handling with ! and try keywords
  • No hidden control flow makes code behavior predictable

Next Steps

In the next lesson, we'll dive deeper into variables and Zig's type system, exploring how to declare variables, work with different data types, and understand type inference.

Ready to continue? Let's explore Variables and Types!

Introduction to Zig | LearningZig.org