# Single-Item Pointers

### Single-Item Pointers

A single-item pointer points to one value.

```zig
var x: i32 = 10;
const p: *i32 = &x;
```

The type `*i32` means that `p` points to one `i32`.

The value is read with `.*`.

```zig
const y = p.*;
```

The value is written with `.*` when the pointed-to value is mutable.

```zig
p.* = 20;
```

A single-item pointer is not an array. It has no length. It does not say where the next item is. It says only that there is one value at this address.

```zig
const std = @import("std");

pub fn main() void {
    var n: i32 = 5;
    const p: *i32 = &n;

    p.* += 1;

    std.debug.print("{d}\n", .{n});
}
```

This prints:

```text
6
```

A function often uses a single-item pointer when it must change one value supplied by the caller.

```zig
fn reset(n: *i32) void {
    n.* = 0;
}
```

The caller passes an address.

```zig
var count: i32 = 17;
reset(&count);
```

After the call, `count` is zero.

Single-item pointers are also useful for large structs. Passing a struct by value copies it. Passing a pointer copies only an address.

```zig
const Buffer = struct {
    data: [4096]u8,
    len: usize,
};

fn clear(buf: *Buffer) void {
    buf.len = 0;
}
```

Here `buf` points to one `Buffer`. The function changes the original buffer.

A single-item pointer may point to mutable data:

```zig
var x: i32 = 1;
const p: *i32 = &x;
```

It may also point to constant data:

```zig
const y: i32 = 1;
const q: *const i32 = &y;
```

A `*const i32` can be read:

```zig
const z = q.*;
```

But it cannot be used to write:

```zig
q.* = 2; // error
```

This rule applies to struct fields too.

```zig
const Point = struct {
    x: i32,
    y: i32,
};

fn printPoint(p: *const Point) void {
    // p.x may be read
    // p.x may not be assigned
}
```

Use `*const T` when a function only observes a value.

```zig
fn lengthSquared(p: *const Point) i32 {
    return p.x * p.x + p.y * p.y;
}
```

Use `*T` when a function may change a value.

```zig
fn moveUp(p: *Point) void {
    p.y += 1;
}
```

This distinction belongs in the type. A caller can see from the function signature whether the function may mutate the value.

Single-item pointers do not support indexing.

```zig
var x: i32 = 10;
const p: *i32 = &x;

// p[0] is not the ordinary way to use this pointer
```

Use `p.*` for the one item.

If you need to refer to many adjacent items, use a slice or a many-item pointer. Those are different types with different meaning.

The type says the promise:

```zig
*T        // one mutable T
*const T  // one constant T
[]T       // many mutable T values with a length
[]const T // many constant T values with a length
```

A single-item pointer may also be optional.

```zig
var x: i32 = 10;
var maybe: ?*i32 = &x;
```

The type `?*i32` means either a pointer to one `i32`, or null.

Before using it, unwrap it.

```zig
if (maybe) |p| {
    p.* += 1;
}
```

This form says: if `maybe` contains a pointer, call it `p` inside the block.

A non-optional pointer cannot be null. That is a major difference from C. If a Zig value has type `*i32`, it is expected to be a valid pointer to an `i32`. When a pointer may be absent, the type must say so with `?`.

This small difference removes many accidental null checks from normal code. Null is not a hidden possibility. It is part of the type when it is possible.

Exercise 5-5. Write `increment` using a `*u32`.

Exercise 5-6. Write `clearPoint` that takes `*Point` and sets both fields to zero.

Exercise 5-7. Write `printPoint` that takes `*const Point`.

Exercise 5-8. Create a `?*i32`, unwrap it with `if`, and change the pointed-to value.

