Language: EN

cheatsheet-zig

Zig CheatSheet

Zig is a systems programming language designed to be robust, fast, and easy to learn.

It offers manual memory management, low-level control, and is an excellent choice for those looking to develop high-performance systems and software.

Installation

Install Zig on Linux

sudo apt install zig

Install Zig on Windows

  1. Download the latest version of Zig from the official site.
  2. Extract the ZIP file and add the directory to the PATH environment variable.

Verify the installation

To verify that Zig is installed correctly, run:

zig version

Introduction

Basic Compilation

To compile a Zig file

zig build-exe file.zig

Direct Execution

To run directly

zig run file.zig

Basic Structure of a Zig Program

const std = @import("std");

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

Data Types in Zig

Zig has simple data types, such as integers, floating-point numbers, and pointers, as well as composite types like structures and arrays.

Integers

  • i8, i16, i32, i64: Signed integers.
  • u8, u16, u32, u64: Unsigned integers.
var a: i32 = 42;
var b: u64 = 100;

Floating-Point Numbers

  • f16, f32, f64: Floating-point numbers.
var pi: f32 = 3.14159;

Booleans

  • bool: Can be true or false.
var is_open: bool = true;

Strings

  • Strings are arrays of characters ([]const u8).
const greeting: []const u8 = "Hello, Zig!";

Variables and Constants

Variables

Declared with var. Their value can change.

const pi: f32 = 3.14; // constant
var counter: i32 = 0; // variable

Constants

Declared with const. Their value cannot change.

const pi: f32 = 3.14; // constant
var counter: i32 = 0; // variable

Operators

Arithmetic

  • Addition: +
  • Subtraction: -
  • Multiplication: *
  • Division: /
  • Modulo: %
var x = 10 + 5; // 15
var y = 10 % 3; // 1

Comparison

  • Equal: ==
  • Not equal: !=
  • Greater: >
  • Less: <
  • Greater or equal: >=
  • Less or equal: <=
if x == 10 {
    // code
}

Control Flow

Conditionals

If - Else

if x > 10 {
    // code if the condition is true
} else {
    // code if the condition is false
}

Switch

switch (x) {
    1 => std.debug.print("One\n", .{}),
    2 => std.debug.print("Two\n", .{}),
    else => std.debug.print("Another number\n", .{}),
}

Loops

For

for (i32(i = 0); i < 10; i += 1) {
    std.debug.print("i: {}\n", .{i});
}

While

var i: i32 = 0;
while (i < 10) : (i += 1) {
    // code that runs while i is less than 10
}

For in collections

const arr = [_]i32{1, 2, 3};
for (arr) |value| {
    // value contains the elements of the array
}

Functions

Function Definition

Zig allows defining functions with arguments and return values.

fn sum(a: i32, b: i32) i32 {
    return a + b;
}
  • The pub prefix makes the function public (visible from other Zig files).
  • If nothing is returned, the return type is void.

Function Call

const result = sum(5, 3);
std.debug.print("Result: {}\n", .{result});

Anonymous Functions (lambdas)

const multiply = fn (a: i32, b: i32) i32 {
    return a * b;
};

Inline Functions

fn square(x: i32) i32 {
    return x * x;
}

const result = square(5);

Generic Functions

fn swapGeneric(behavior: anytype, a: anytype, b: anytype) void {
    var temp: anytype = a;
    a = b;
    b = temp;
}

Composite Types

Arrays

Arrays are fixed-length types.

const numbers: [5]i32 = [5]i32{1, 2, 3, 4, 5};

Slices

const slice = &numbers[1..4]; // Access elements from index 1 to 3
std.debug.print("Elements in slice: {}\n", .{slice});

Structures

Structures (structs) are custom data types that can contain multiple values.

const Point = struct {
    x: i32,
    y: i32,
};
const point: Point = Point { .x = 10, .y = 20 };

Enumerations

Enumerations (enum) define a set of possible values for a variable.

const State = enum {
    Inactive,
    Active,
};
const state: State = State.Active;

Unions

const Value = union {
    integer: i32,
    decimal: f32,
};

var v: Value = Value{ .integer = 10 };
std.debug.print("Integer value: {}\n", .{v.integer});

Memory Management

Pointers

Zig allows manual pointer management.

var x: i32 = 42;
var ptr: *i32 = &x;

Memory Allocation

const memory = std.heap.page_allocator;
const ptr = try memory.allocate(i32, 1);
ptr.* = 42;
defer memory.deallocate(ptr);

Memory Release

Zig does not have a garbage collector, so memory allocation and release must be done manually.

var allocator = std.heap.page_allocator;
const buffer = try allocator.alloc(u8, 1024); // allocate 1024 bytes

defer allocator.free(buffer); // release memory

Defer

defer executes a statement just before the function ends. Useful for releasing resources.

const std = @import("std");

pub fn main() void {
    var file = try std.fs.cwd().openFile("file.txt", .{});
    defer file.close(); // executed just before the function ends
}

Error Handling

Zig does not use exceptions. Instead, it employs an error handling system based on the use of try, catch, and error codes.

Explicit Errors

Functions can return errors that must be handled.

fn division(a: i32, b: i32) !i32 {
    if (b == 0) {
        return error.DivisionByZero;
    }
    return a / b;
}

Try - Catch

  • try: Executes an operation that may fail. If it fails, it returns the error to the caller.
  • catch: Catches errors.
const file = try std.fs.cwd().openFile("file.txt", .{}).catch |err| {
    std.debug.print("Failed to open file: {}\n", .{err});
};

Asserts

const a: i32 = 5;
const b: i32 = 10;
assert(a < b, "a must be less than b");

Concurrency

Zig has support for asynchronous tasks using async and await.

Defining Asynchronous Functions

fn get_data_async() async i32 {
    return 42;
}

pub fn main() void {
    const data = await get_data_async();
}

Modules

Creating Modules

Create a file named my_module.zig.

pub fn moduleFunction() void {
    std.debug.print("Module function called\n", .{});
}

Importing Modules

const std = @import("std");
const my_module = @import("my_module.zig");

pub fn main() void {
    my_module.moduleFunction();
}

Interoperability with C

Zig allows importing and using C code directly.

Importing C

const c = @cImport({
    @cInclude("stdio.h");
});

pub fn main() void {
    c.printf("Hello from C!\n");
}

Zig can also compile C files along with Zig. This is useful for integrating C libraries into Zig projects.