Skip to content

Defining Functions

A function groups statements into a single operation. Functions are the basic unit of organization in a Zig program.

A function groups statements into a single operation. Functions are the basic unit of organization in a Zig program.

Here is a small function:

const std = @import("std");

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

pub fn main() void {
    const n = square(5);
    std.debug.print("{d}\n", .{n});
}

The output is:

25

A function declaration has four parts:

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

fn begins the declaration.

square is the function name.

(x: i32) is the parameter list.

The i32 after the parameter list is the return type.

The body of the function is enclosed in braces.

The statement:

return x * x;

returns a value to the caller.

Functions may take more than one parameter:

fn max(a: i32, b: i32) i32 {
    if (a > b) {
        return a;
    }

    return b;
}

Parameters are separated by commas. Each parameter has both a name and a type.

Functions that do not return a value use the type void:

fn banner() void {
    std.debug.print("zig\n", .{});
}

A function call is an expression:

const x = square(7);

The arguments are evaluated, then control passes to the function. When the function returns, the call expression is replaced by the returned value.

Functions may call other functions:

const std = @import("std");

fn double(x: i32) i32 {
    return x * 2;
}

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

fn compute(x: i32) i32 {
    return square(double(x));
}

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

The output is:

36

Function names follow the same rules as other identifiers. By convention, Zig uses camelCase names:

fn readFile() void {}
fn parseNumber() void {}
fn printReport() void {}

A function can be declared before or after it is used:

const std = @import("std");

pub fn main() void {
    greet();
}

fn greet() void {
    std.debug.print("hello\n", .{});
}

The compiler processes declarations for the whole file, so order usually does not matter.

Local variables belong to the function in which they are declared:

fn f() void {
    const x = 1;
}

fn g() void {
    // x is not visible here
}

The names inside one function are normally hidden from other functions.

A function may contain many return statements:

fn abs(x: i32) i32 {
    if (x < 0) {
        return -x;
    }

    return x;
}

As soon as return executes, the function ends.

Small functions are common in Zig. The language encourages programs built from simple pieces with explicit inputs and outputs.

Exercise 4-1. Write a function cube that returns the cube of an integer.

Exercise 4-2. Write a function isEven that returns true if a number is even.

Exercise 4-3. Write a program with three functions: add, sub, and mul.

Exercise 4-4. What happens if a function declares return type i32 but does not return a value?