Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. Zig Dictionary
  3. Pointer Basics (*T / &variable)

Pointer Basics (*T / &variable)

In Zig, pointers let you store and work with memory addresses of variables, reading and writing values through those addresses. A pointer type is written as *T (where T is the type being pointed to). Use &variable to obtain an address and pointer.* to dereference it. The mechanism is similar to C, but Zig pointers are designed to be safe by not allowing null by default.

Syntax

// -----------------------------------------------
// *T — Declaring a pointer type and obtaining a pointer
// -----------------------------------------------

var variable: T = value;
const ptr: *T = &variable;   // Use & to get the address and obtain a pointer

// -----------------------------------------------
// Dereferencing a pointer
// -----------------------------------------------

const value = ptr.*;        // Read the value at the address using ptr.*
ptr.* = new_value;          // Assign to ptr.* to write through the pointer
                            // Note: a const pointer (*const T) cannot be written to

// -----------------------------------------------
// *const T — Read-only pointer
// -----------------------------------------------

const variable: T = value;
const ptr: *const T = &variable;  // A pointer to a const variable becomes *const T
// ptr.* = new_value;             // Compile error: cannot write through a const pointer

// -----------------------------------------------
// Function that takes a pointer argument (pass by reference)
// -----------------------------------------------

fn functionName(ptr: *T) void {
    ptr.* = new_value;    // Modifies the caller's variable directly
}
functionName(&variable);  // Pass the address using &

Syntax Reference

Syntax / KeywordDescription
*TA (mutable) pointer type pointing to a value of type T.
*const TA read-only pointer type pointing to a value of type T. The pointed-to value cannot be changed.
&variableTakes the address of a variable and produces a pointer.
ptr.*Dereferences the pointer to read the value it points to.
ptr.* = valueWrites a value through the pointer. Not available for *const T.
fn f(ptr: *T) voidA function that accepts a pointer argument. It can modify the caller's variable directly.
f(&variable)Passes the address of a variable to a function using & (equivalent to pass by reference).

Sample Code

evangelion_pointer.zig
// evangelion_pointer.zig — Basic examples of pointer *T
// Uses Evangelion characters to demonstrate
// obtaining addresses, dereferencing, and passing by reference

// Import the standard library
const std = @import("std");

// -----------------------------------------------
// Updates the sync rate via a pointer argument
// Taking *u32 allows direct modification of the caller's variable
// -----------------------------------------------
fn updateSyncRate(rate: *u32, new_rate: u32) void {
    rate.* = new_rate;  // Dereference and write the new value
}

pub fn main() !void {
    // Get a writer for standard output
    const stdout = std.io.getStdOut().writer();

    // -----------------------------------------------
    // Basics: obtaining a pointer and dereferencing it
    // -----------------------------------------------

    // Declare Shinji's initial sync rate with var (required because we write through a pointer)
    var shinji_sync: u32 = 41;

    // Use & to get the address of shinji_sync and obtain a *u32 pointer
    const shinji_ptr: *u32 = &shinji_sync;

    try stdout.print("=== Unit-01 Pilot: Ikari Shinji ===\n", .{});

    // Print the integer with {d}
    try stdout.print("Sync rate (variable): {d}%\n", .{shinji_sync});

    // Read the value through the pointer with ptr.*
    try stdout.print("Sync rate (via pointer): {d}%\n", .{shinji_ptr.*});

    // Write a new value through the pointer
    shinji_ptr.* = 400;
    try stdout.print("Sync rate after limit break: {d}%\n", .{shinji_sync});

    // -----------------------------------------------
    // *const T — Read-only pointer
    // -----------------------------------------------

    // Rei's pilot number never changes, so declare it with const
    const rei_pilot_no: u32 = 0;

    // A pointer to a const variable has type *const u32
    const rei_ptr: *const u32 = &rei_pilot_no;

    try stdout.print("\n=== Unit-00 Pilot: Ayanami Rei ===\n", .{});
    try stdout.print("Pilot number (read-only): {d}\n", .{rei_ptr.*});
    // rei_ptr.* = 1; // Compile error: cannot write through *const T

    // -----------------------------------------------
    // Passing a pointer to a function (pass by reference)
    // -----------------------------------------------

    // Initialize Asuka's sync rate
    var asuka_sync: u32 = 50;

    try stdout.print("\n=== Unit-02 Pilot: Sohryu Asuka Langley ===\n", .{});
    try stdout.print("Sync rate during training: {d}%\n", .{asuka_sync});

    // Passing & sends the address; writes inside the function are reflected in the caller
    updateSyncRate(&asuka_sync, 98);
    try stdout.print("Sync rate after real combat: {d}%\n", .{asuka_sync});

    updateSyncRate(&asuka_sync, 400);
    try stdout.print("Sync rate after Berserk activation: {d}%\n", .{asuka_sync});

    // -----------------------------------------------
    // Pointer operations on multiple variables
    // -----------------------------------------------

    var kaworu_sync: u32 = 99;
    var misato_level: u32 = 3;  // Misato's threat assessment level for Kaworu

    // Obtain separate pointers to different variables
    const kaworu_ptr: *u32 = &kaworu_sync;
    const misato_ptr: *u32 = &misato_level;

    try stdout.print("\n=== Nagisa Kaworu / Katsuragi Misato Assessment ===\n", .{});
    try stdout.print("Kaworu sync rate: {d}%\n", .{kaworu_ptr.*});
    try stdout.print("Misato alert level: {d}\n", .{misato_ptr.*});

    // Update both variables through their pointers
    kaworu_ptr.* = 100;
    misato_ptr.* = 5;

    try stdout.print("After update — Kaworu sync rate: {d}%\n", .{kaworu_sync});
    try stdout.print("After update — Misato alert level: {d}\n", .{misato_level});
}
zig run evangelion_pointer.zig
=== Unit-01 Pilot: Ikari Shinji ===
Sync rate (variable): 41%
Sync rate (via pointer): 41%
Sync rate after limit break: 400%

=== Unit-00 Pilot: Ayanami Rei ===
Pilot number (read-only): 0

=== Unit-02 Pilot: Sohryu Asuka Langley ===
Sync rate during training: 50%
Sync rate after real combat: 98%
Sync rate after Berserk activation: 400%

=== Nagisa Kaworu / Katsuragi Misato Assessment ===
Kaworu sync rate: 99%
Misato alert level: 3
After update — Kaworu sync rate: 100%
After update — Misato alert level: 5

Overview

The pointer type *T in Zig holds a memory address where a value of type T is stored. Use &variable to take the address of a variable and obtain a pointer, and use pointer.* to read or write the value at that address — equivalent to *ptr in C. When a value does not need to be modified, use *const T (a read-only pointer) to prevent accidental writes at compile time. Accepting *T as a function parameter has the same effect as pass by reference, allowing the function to modify the caller's variable directly. Note that Zig pointers do not allow null by default. To handle null, use an optional pointer (?*T). For details on optional types, see Optional Type ?T. For slices (pointers to multiple elements), see Slices.

If you find any errors or copyright issues, please .