Skip to content

Names and Declarations

A Zig program is made from declarations.

A Zig program is made from declarations.

A declaration gives a name to something. The name may refer to a value, a function, a type, or an imported module.

const std = @import("std");

const count = 10;

pub fn main() void {
    std.debug.print("{d}\n", .{count});
}

There are three declarations here.

const std = @import("std");

This declares the name std.

const count = 10;

This declares the name count.

pub fn main() void {
    ...
}

This declares the function main.

A const declaration has this form:

const name = value;

The name is fixed. It cannot later be assigned another value.

const n = 3;
n = 4; // error

A var declaration has this form:

var name = value;

The name may be assigned another value.

var n = 3;
n = 4;

A declaration may also give the type explicitly.

const x: i32 = 10;
var y: i32 = 20;

The part after the colon is the type. Here both x and y have type i32, a signed 32-bit integer.

When the type is omitted, Zig infers it from the value.

const x = 10;

This is often enough. But explicit types are useful when the exact size matters.

const small: u8 = 255;

u8 is an unsigned 8-bit integer. It can hold values from 0 to 255.

A name is visible inside its scope. A scope is a region of code surrounded by braces.

pub fn main() void {
    const a = 1;

    {
        const b = 2;
        std.debug.print("{d} {d}\n", .{ a, b });
    }

    std.debug.print("{d}\n", .{a});
    // b is not visible here
}

The name a is visible in the whole function after its declaration. The name b is visible only inside the inner block.

Declarations at the top level of a file are file declarations.

const std = @import("std");
const message = "hello";

pub fn main() void {
    std.debug.print("{s}\n", .{message});
}

The function main can use std and message because they are declared at file scope.

A declaration can be public.

pub const version = 1;

pub means the declaration can be used from another file that imports this file. Without pub, the declaration is private to the file.

Function declarations use fn.

fn add(a: i32, b: i32) i32 {
    return a + b;
}

This declares a function named add. It takes two i32 values and returns an i32.

A public function uses pub fn.

pub fn main() void {
    const sum = add(2, 3);
    std.debug.print("{d}\n", .{sum});
}

Zig does not require declarations to appear before use at file scope. This is valid:

const std = @import("std");

pub fn main() void {
    const sum = add(2, 3);
    std.debug.print("{d}\n", .{sum});
}

fn add(a: i32, b: i32) i32 {
    return a + b;
}

The compiler sees the whole file.

Inside a block, declarations are read in order. A local name must be declared before it is used.

pub fn main() void {
    const x = 1;
    const y = x + 1;
    std.debug.print("{d}\n", .{y});
}

A name should say what the value means.

const bytes_read = 128;
const max_line_len = 4096;

Short names are useful for small local values.

var i: usize = 0;

Longer names are better when the value lives longer or carries more meaning.

const input_file_name = "data.txt";

A declaration is simple, but it is the main unit of Zig code. You declare names, give them values or definitions, and use those names to build the program.

Exercises:

  1. Declare a constant named answer with value 42 and print it.

  2. Declare a variable named n, set it to 1, then assign 2, then print it.

  3. Write a function square that takes an i32 and returns its square.

  4. Move square below main and verify that the program still compiles.

  5. Create an inner block with a local constant, then try to use that constant outside the block.