zig-skills/references/builtins.md

17 KiB

Selected Zig Built-in Functions Reference

Built-in functions are compiler intrinsics prefixed with @. Parameters marked comptime must be compile-time known. This is a practical reference to commonly used built-ins, not an exhaustive inventory; consult the language reference when completeness matters.

Table of Contents

Type Conversions

@as

@as(comptime T: type, expr) T

Safe type coercion. Preferred over explicit casts when conversion is unambiguous.

const x = @as(u32, 5);  // comptime_int → u32

@intCast

@intCast(value: anytype) anytype

Convert between integer types. Runtime safety check if value doesn't fit.

const big: u64 = 100;
const small: u8 = @intCast(big);  // OK if value fits

@floatCast

@floatCast(value: anytype) anytype

Convert between float types. Return type inferred.

const d: f64 = 3.14;
const f: f32 = @floatCast(d);

@intFromFloat

@intFromFloat(value: anytype) anytype

Float → integer. Truncates fractional part. Return type inferred.

const i: i32 = @intFromFloat(3.7);  // i = 3

@floatFromInt

@floatFromInt(value: anytype) anytype

Integer → float. Return type inferred.

const f: f32 = @floatFromInt(42);

@intFromPtr

@intFromPtr(ptr: anytype) usize

Pointer → usize. For pointer arithmetic or FFI.

const addr: usize = @intFromPtr(&x);

@ptrFromInt

@ptrFromInt(addr: usize) anytype

usize → pointer. Return type inferred. Undefined behavior if invalid.

const ptr: *u32 = @ptrFromInt(0x1000);

@ptrCast

@ptrCast(ptr: anytype) anytype

Pointer type cast. Return type inferred.

const bytes: [*]u8 = @ptrCast(some_ptr);

@alignCast

@alignCast(ptr: anytype) anytype

Change pointer alignment. Safety check at runtime.

const aligned: *align(16) u8 = @alignCast(ptr);

@constCast

@constCast(ptr: anytype) anytype

Remove const qualifier from pointer. Return type inferred.

const mutable_ptr: *u32 = @constCast(const_ptr);

@volatileCast

@volatileCast(ptr: anytype) anytype

Remove volatile qualifier from pointer.

@bitCast

@bitCast(value: anytype) anytype

Reinterpret bits as different type. Sizes must match. Return type inferred.

const bits: u32 = @bitCast(@as(f32, 1.0));
const f: f32 = @bitCast(@as(u32, 0x3f800000));

@truncate

@truncate(value: anytype) anytype

Truncate integer to smaller type. Discards high bits. Return type inferred.

const small: u8 = @truncate(@as(u32, 0x12345678));  // 0x78

@intFromBool

@intFromBool(value: bool) u1

false → 0, true → 1.

const x: u8 = @intFromBool(true);  // 1

@intFromEnum

@intFromEnum(value: anytype) anytype

Enum → backing integer type.

const State = enum(u8) { idle = 0, running = 1 };
const n: u8 = @intFromEnum(State.running);  // 1

@enumFromInt

@enumFromInt(int: anytype) anytype

Integer → enum. Return type inferred.

const state: State = @enumFromInt(1);  // State.running

@errorFromInt

@errorFromInt(int: anytype) anytype

Integer → error. Return type inferred.

@intFromError

@intFromError(err: anytype) std.meta.Int(.unsigned, @bitSizeOf(anyerror))

Error → integer.

@errorCast

@errorCast(err: anytype) anytype

Cast between error set types.

@addrSpaceCast

@addrSpaceCast(ptr: anytype) anytype

Convert pointer between address spaces (GPU/embedded).

Integer/Float Operations

@abs

@abs(value: anytype) anytype

Absolute value. Works on integers, floats, vectors.

const x = @abs(@as(i32, -5));  // 5

@min / @max

@min(a: T, b: T, ...) T
@max(a: T, b: T, ...) T

Return the minimum/maximum of two or more values.

const m = @max(3, 7);  // 7

@divExact

@divExact(numerator: T, denominator: T) T

Exact division. Asserts no remainder.

const x = @divExact(10, 2);  // 5

@divFloor

@divFloor(numerator: T, denominator: T) T

Floor division (rounds toward negative infinity).

const x = @divFloor(-7, 3);  // -3

@divTrunc

@divTrunc(numerator: T, denominator: T) T

Truncating division (rounds toward zero).

const x = @divTrunc(-7, 3);  // -2

@mod

@mod(numerator: T, denominator: T) T

Floor modulus. Result has same sign as denominator.

const x = @mod(-5, 3);  // 1

@rem

@rem(numerator: T, denominator: T) T

Remainder. Result has same sign as numerator.

const x = @rem(-5, 3);  // -2

Math Functions (floats/vectors)

@sqrt(x)     // Square root
@sin(x)      // Sine
@cos(x)      // Cosine
@tan(x)      // Tangent
@exp(x)      // e^x
@exp2(x)     // 2^x
@log(x)      // Natural log
@log2(x)     // Log base 2
@log10(x)    // Log base 10
@floor(x)    // Round down
@ceil(x)     // Round up
@round(x)    // Round to nearest
@trunc(x)    // Truncate toward zero
@mulAdd(T, a, b, c)  // Fused (a*b)+c

Overflow Arithmetic

Returns tuple: { result, overflow_bit } where overflow_bit is u1.

@addWithOverflow

@addWithOverflow(a: T, b: T) struct { T, u1 }
const result, const overflow = @addWithOverflow(@as(u8, 250), 10);
if (overflow != 0) { /* handle overflow */ }

@subWithOverflow

@subWithOverflow(a: T, b: T) struct { T, u1 }

@mulWithOverflow

@mulWithOverflow(a: T, b: T) struct { T, u1 }

@shlWithOverflow

@shlWithOverflow(a: T, b: Log2Int) struct { T, u1 }

Bit Manipulation

@clz

@clz(value: anytype) anytype

Count leading zeros.

const z = @clz(@as(u8, 0b00001111));  // 4

@ctz

@ctz(value: anytype) anytype

Count trailing zeros.

const z = @ctz(@as(u8, 0b11110000));  // 4

@popCount

@popCount(value: anytype) anytype

Count set bits (population count).

const c = @popCount(@as(u8, 0b10101010));  // 4

@byteSwap

@byteSwap(value: anytype) @TypeOf(value)

Reverse byte order (endianness conversion).

const swapped = @byteSwap(@as(u32, 0x12345678));  // 0x78563412

@bitReverse

@bitReverse(value: anytype) @TypeOf(value)

Reverse all bits.

const rev = @bitReverse(@as(u8, 0b11000001));  // 0b10000011

@shlExact / @shrExact

@shlExact(value: T, shift: Log2Int) T
@shrExact(value: T, shift: Log2Int) T

Shift with assertion that no bits are lost.

Memory Operations

@memcpy

@memcpy(dest: []T, src: []const T) void

Copy memory. Slices must not overlap.

@memcpy(dest[0..n], src[0..n]);

@memset

@memset(dest: []T, value: T) void

Fill memory with value.

@memset(buffer[0..n], 0);

@memmove

@memmove(dest: []T, src: []const T) void

Copy memory. Slices may overlap.

@sizeOf

@sizeOf(comptime T: type) comptime_int

Size of type in bytes (includes padding).

const size = @sizeOf(u32);  // 4

@bitSizeOf

@bitSizeOf(comptime T: type) comptime_int

Size of type in bits.

const bits = @bitSizeOf(u24);  // 24

@alignOf

@alignOf(comptime T: type) comptime_int

Alignment requirement of type.

const align = @alignOf(u64);  // typically 8

@offsetOf

@offsetOf(comptime T: type, comptime field: []const u8) comptime_int

Byte offset of struct field.

const Point = struct { x: i32, y: i32 };
const off = @offsetOf(Point, "y");  // 4

@bitOffsetOf

@bitOffsetOf(comptime T: type, comptime field: []const u8) comptime_int

Bit offset of field (useful for packed structs).

Atomics

@atomicLoad

@atomicLoad(comptime T: type, ptr: *const T, comptime ordering: AtomicOrder) T

Atomic read.

const val = @atomicLoad(u32, &counter, .acquire);

@atomicStore

@atomicStore(comptime T: type, ptr: *T, value: T, comptime ordering: AtomicOrder) void

Atomic write.

@atomicStore(u32, &counter, 42, .release);

@atomicRmw

@atomicRmw(comptime T: type, ptr: *T, comptime op: AtomicRmwOp, operand: T, comptime ordering: AtomicOrder) T

Atomic read-modify-write. Returns previous value.

const old = @atomicRmw(u32, &counter, .Add, 1, .seq_cst);

Operations: .Add, .Sub, .And, .Or, .Xor, .Nand, .Min, .Max, .Xchg

@cmpxchgStrong / @cmpxchgWeak

@cmpxchgStrong(comptime T: type, ptr: *T, expected: T, new: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T
@cmpxchgWeak(comptime T: type, ptr: *T, expected: T, new: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T

Compare-and-swap. Returns null on success, old value on failure.

while (@cmpxchgWeak(u32, &counter, expected, new, .seq_cst, .seq_cst)) |actual| {
    expected = actual;
}

Type Introspection

@TypeOf

@TypeOf(expr) type

Get type of expression at comptime.

const T = @TypeOf(some_value);

@typeInfo

@typeInfo(comptime T: type) std.builtin.Type

Get detailed type information.

const info = @typeInfo(MyStruct);
if (info == .@"struct") {
    for (info.@"struct".fields) |field| {
        // field.name, field.type, etc.
    }
}

@Type - removed in Zig 0.16

@Type was removed in Zig 0.16. Use the specific type-construction builtin that matches the type you are creating:

Common replacements:

  • integer type: @Int(.signed, 32)
  • tuple type: @Tuple(&.{ u32, []const u8 })
  • pointer type: @Pointer(...)
  • function type: @Fn(...)
  • struct type: @Struct(...)
  • union type: @Union(...)
  • enum type: @Enum(...)
  • opaque type: write opaque {} directly

Keep @typeInfo for reflection; use the new builtins only when constructing types.

@typeName

@typeName(comptime T: type) [:0]const u8

Get string name of type.

const name = @typeName(u32);  // "u32"

@hasDecl

@hasDecl(comptime T: type, comptime name: []const u8) bool

Check if type has declaration (const, fn, etc.).

if (@hasDecl(T, "init")) { T.init(); }

@hasField

@hasField(comptime T: type, comptime name: []const u8) bool

Check if struct/union has field.

@field

@field(value: anytype, comptime name: []const u8) anytype

Access field by comptime string name.

const x = @field(point, "x");

@FieldType

@FieldType(comptime T: type, comptime name: []const u8) type

Get type of a struct field.

@fieldParentPtr

@fieldParentPtr(comptime field_name: []const u8, field_ptr: anytype) anytype

Get pointer to containing struct from field pointer (for intrusive data structures).

const Node = struct { data: u32, hook: Hook };
fn getNode(hook: *Hook) *Node {
    return @fieldParentPtr("hook", hook);
}

@tagName

@tagName(value: anytype) [:0]const u8

Get string name of enum/union tag.

const Color = enum { red, green, blue };
const name = @tagName(Color.red);  // "red"

@errorName

@errorName(err: anyerror) [:0]const u8

Get string name of error.

const name = @errorName(error.OutOfMemory);  // "OutOfMemory"

Comptime Utilities

@import

@import(comptime path: []const u8) type

Import module. Special: "std", "builtin".

const std = @import("std");
const builtin = @import("builtin");
const other = @import("other.zig");

@embedFile

@embedFile(comptime path: []const u8) *const [N:0]u8

Embed file contents as compile-time string.

const data = @embedFile("data.bin");

@compileError

@compileError(comptime msg: []const u8) noreturn

Emit compile error with message.

if (condition) @compileError("Invalid configuration");

@compileLog

@compileLog(args: ...) void

Print values at compile time for debugging.

@compileLog("x =", x, "T =", T);

@This

@This() type

Get enclosing struct/union/enum type.

const Self = @This();
fn method(self: *Self) void { ... }

@src

@src() std.builtin.SourceLocation

Get current source location (module, file, line, column, and function name).

@inComptime

@inComptime() bool

Check if currently executing at comptime.

if (@inComptime()) {
    // comptime path
} else {
    // runtime path
}

@setEvalBranchQuota

@setEvalBranchQuota(quota: u32) void

Increase comptime evaluation limit (default 1000).

@setEvalBranchQuota(100_000);

SIMD/Vector

@Vector

@Vector(len: comptime_int, T: type) type

Create SIMD vector type.

const Vec4f = @Vector(4, f32);
const v: Vec4f = .{ 1.0, 2.0, 3.0, 4.0 };

@splat

@splat(value: anytype) anytype

Create vector with all elements equal to value. Return type inferred.

const ones: @Vector(4, f32) = @splat(1.0);

@reduce

@reduce(comptime op: std.builtin.ReduceOp, value: anytype) ElementType

Reduce vector to scalar.

const sum = @reduce(.Add, vec);  // sum all elements
const max = @reduce(.Max, vec);  // find maximum

Operations: .Add, .Mul, .And, .Or, .Xor, .Min, .Max

@shuffle

@shuffle(T: type, a: @Vector(N, T), b: @Vector(N, T), mask: @Vector(M, i32)) @Vector(M, T)

Rearrange vector elements using mask.

const a: @Vector(4, i32) = .{ 1, 2, 3, 4 };
const b: @Vector(4, i32) = .{ 5, 6, 7, 8 };
const result = @shuffle(i32, a, b, .{ 0, 4, 1, 5 });  // {1, 5, 2, 6}
// Positive indices select from a, indices >= len select from b

@select

@select(T: type, pred: @Vector(N, bool), a: @Vector(N, T), b: @Vector(N, T)) @Vector(N, T)

Element-wise select: pred[i] ? a[i] : b[i].

C Interop

@cImport - deprecated migration path

@cImport(expr) type

Import C header files. In Zig 0.16 this is deprecated as the long-term API; prefer translating headers in build.zig with b.addTranslateC(...) and importing translate_c.createModule().

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

@cInclude

@cInclude(comptime path: []const u8) void

Include C header (inside @cImport).

@cDefine

@cDefine(comptime name: []const u8, value) void

Define C macro (inside @cImport).

@cUndef

@cUndef(comptime name: []const u8) void

Undefine C macro.

@extern

@extern(comptime T: type, options: ExternOptions) T

Declare external symbol.

@export

@export(target: anytype, options: ExportOptions) void

Export symbol. Takes pointer in 0.14.0+.

@export(&my_fn, .{ .name = "exported_name" });

C Varargs

@cVaStart() std.builtin.VaList    // Start vararg processing
@cVaArg(*VaList, T) T             // Get next vararg
@cVaCopy(*VaList) VaList          // Copy vararg state
@cVaEnd(*VaList) void             // End vararg processing

Debug/Control Flow

@branchHint

@branchHint(hint: std.builtin.BranchHint) void

Hint branch likelihood. Must be first statement in branch.

if (unlikely_condition) {
    @branchHint(.cold);
    // rarely executed
}

Hints: .none, .likely, .unlikely, .cold, .unpredictable

@breakpoint

@breakpoint() void

Insert debugger breakpoint.

@trap

@trap() noreturn

Crash immediately (illegal instruction).

@panic

@panic(msg: []const u8) noreturn

Trigger panic with message.

@setRuntimeSafety

@setRuntimeSafety(enabled: bool) void

Enable/disable safety checks in current scope.

@setRuntimeSafety(false);
// Unsafe operations here

@setFloatMode

@setFloatMode(mode: std.builtin.FloatMode) void

Set floating-point optimization mode.

@setFloatMode(.optimized);  // Allow reordering, etc.

@returnAddress

@returnAddress() usize

Get return address of current function.

@frameAddress

@frameAddress() usize

Get frame pointer of current function.

@errorReturnTrace

@errorReturnTrace() ?*std.builtin.StackTrace

Get error return trace (if available).

@call

@call(modifier: std.builtin.CallModifier, fn: anytype, args: anytype) anytype

Call function with modifier.

const result = @call(.always_inline, my_fn, .{ arg1, arg2 });

Modifiers: .auto, .never_inline, .always_inline, .always_tail, .never_tail, .compile_time, .no_suspend. The .no_suspend modifier asserts that the call will not suspend.

@prefetch

@prefetch(ptr: anytype, options: PrefetchOptions) void

Prefetch memory into cache.

@prefetch(ptr, .{ .rw = .read, .locality = 3 });

WebAssembly

@wasmMemorySize

@wasmMemorySize(index: u32) u32

Get WebAssembly memory size in pages.

@wasmMemoryGrow

@wasmMemoryGrow(index: u32, delta: u32) u32

Grow WebAssembly memory by delta pages.

GPU/Workgroup

@workGroupId(dim: u32) u32      // Get workgroup ID
@workGroupSize(dim: u32) u32    // Get workgroup size
@workItemId(dim: u32) u32       // Get work item ID within group