Skip to content

Appendix C. Builtin Functions

Builtin functions are part of the language. Their names begin with @.

Builtin functions are part of the language. Their names begin with @.

This appendix gives the common builtins by purpose. It is not a complete replacement for the language reference.

C.1 Import and Type Information

@import("std")
@This()
@TypeOf(x)

@import loads a package or source file.

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

@This gives the current container type.

const Node = struct {
    const Self = @This();

    value: i32,
    next: ?*Self,
};

@TypeOf gives the type of an expression.

const T = @TypeOf(123);

C.2 Size and Alignment

@sizeOf(T)
@alignOf(T)
@bitSizeOf(T)
@offsetOf(T, "field")

Example:

const std = @import("std");

pub fn main() void {
    std.debug.print("size = {d}\n", .{@sizeOf(u64)});
}

@sizeOf counts bytes. @bitSizeOf counts bits. @alignOf gives the ABI alignment.

C.3 Type Conversion

@as(T, x)
@intCast(x)
@floatCast(x)
@ptrCast(p)
@alignCast(p)
@bitCast(x)

Examples:

const x: i32 = @intCast(n);
const y: f32 = @floatCast(z);
const p: *T = @ptrCast(raw);

Use casts where the program needs a precise type. Do not use casts to hide a bad design.

C.4 Integer Conversion

@intFromFloat(x)
@floatFromInt(x)
@intFromEnum(x)
@enumFromInt(x)
@intFromPtr(p)
@ptrFromInt(addr)

Example:

const n: i32 = @intFromFloat(12.0);
const f: f64 = @floatFromInt(n);

Pointer-integer conversion is low-level code. It belongs in allocators, kernels, device code, and foreign interfaces.

C.5 Arithmetic

@addWithOverflow(a, b)
@subWithOverflow(a, b)
@mulWithOverflow(a, b)
@shlWithOverflow(a, b)

Example:

const r = @addWithOverflow(a, b);
if (r[1] != 0) {
    return error.Overflow;
}
const sum = r[0];

The result contains the computed value and an overflow flag.

C.6 Division and Remainder

@divExact(a, b)
@divFloor(a, b)
@divTrunc(a, b)
@mod(a, b)
@rem(a, b)

Example:

const q = @divFloor(a, b);
const r = @mod(a, b);

Use these when signed division must have a clear rule.

C.7 Bit Operations

@clz(x)
@ctz(x)
@popCount(x)
@byteSwap(x)
@bitReverse(x)

Example:

const ones = @popCount(mask);

These map well to machine instructions on most targets.

C.8 Memory

@memcpy(dest, source)
@memset(dest, value)

Example:

@memset(buf, 0);
@memcpy(dst, src);

The source and destination must have compatible lengths.

C.9 Compile-Time Reflection

@typeInfo(T)
@Type(info)
@hasDecl(T, "name")
@hasField(T, "field")
@field(x, "name")

Example:

fn hasLen(comptime T: type) bool {
    return @hasField(T, "len");
}

Reflection is ordinary Zig code evaluated at compile time.

C.10 Compile-Time Control

@compileError("message")
@compileLog(x)

Example:

fn requireInt(comptime T: type) void {
    if (@typeInfo(T) != .int) {
        @compileError("expected integer type");
    }
}

@compileLog is for debugging compile-time code. Remove it when finished.

C.11 Calling and Inlining

@call(modifier, function, args)

The modifier controls call behavior.

Common forms include ordinary calls, inline calls, and never-inline calls.

Most code should use normal function-call syntax.

C.12 Atomics

@atomicLoad(T, ptr, ordering)
@atomicStore(T, ptr, value, ordering)
@atomicRmw(T, ptr, op, value, ordering)
@cmpxchgWeak(T, ptr, expected, new_value, success_order, fail_order)
@cmpxchgStrong(T, ptr, expected, new_value, success_order, fail_order)

Example:

const old = @atomicRmw(u32, &counter, .add, 1, .monotonic);

Atomics are for shared memory between threads or hardware agents. Use the weakest ordering that proves correct.

C.13 Error Return Tracing

@errorReturnTrace()

This returns the current error return trace when tracing is enabled.

if (@errorReturnTrace()) |trace| {
    _ = trace;
}

C.14 Source Location

@src()

Example:

const here = @src();

It returns compile-time information about the current source location.

C.15 Panic and Trap

@panic("message")
@trap()

@panic stops with a message.

if (bad) {
    @panic("invalid state");
}

@trap emits a target trap instruction.

C.16 Branch Hints and Optimization

@branchHint(.likely)
@branchHint(.unlikely)
@setEvalBranchQuota(n)

Branch hints are rarely needed.

if (fast_path) {
    @branchHint(.likely);
    runFast();
}

@setEvalBranchQuota raises the branch quota for compile-time evaluation.

C.17 ABI and Target

@cImport(...)
@cInclude("file.h")
@cDefine("NAME", "VALUE")
@cUndef("NAME")

Example:

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

These are used for C interoperation.

C.18 Assembly

asm volatile (...)

Inline assembly is target-specific and should be isolated behind small functions.

fn halt() noreturn {
    while (true) {
        asm volatile ("hlt");
    }
}

C.19 Common Rule

A builtin should make the program more explicit. If it only makes the program clever, remove it.