# Optional Pointers

### Optional Pointers

Pointers are often optional.

A search may not find an object. A tree node may not have a parent. A linked list node may not have a next node.

In Zig, this is written explicitly:

```zig
?*i32
```

This means:

> either a pointer to `i32`, or `null`

A normal pointer:

```zig
*i32
```

cannot be null.

This difference matters.

Here is a simple example:

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

pub fn main() void {
    var number: i32 = 123;

    const p: ?*i32 = &number;

    if (p) |ptr| {
        std.debug.print("{d}\n", .{ptr.*});
    }
}
```

The output is:

```text
123
```

The expression:

```zig
ptr.*
```

dereferences the pointer.

The payload capture:

```zig
if (p) |ptr|
```

unwraps the optional pointer before use.

If the pointer is null:

```zig
const p: ?*i32 = null;
```

the block is skipped.

Optional pointers are common in data structures.

A linked list node might look like this:

```zig
const Node = struct {
    value: i32,
    next: ?*Node,
};
```

`next` may point to another node, or it may be `null`.

The last node in the list has:

```zig
next = null
```

This style is direct and compact. There is no hidden nullable state.

Here is a small traversal example:

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

const Node = struct {
    value: i32,
    next: ?*Node,
};

pub fn main() void {
    var third = Node{
        .value = 30,
        .next = null,
    };

    var second = Node{
        .value = 20,
        .next = &third,
    };

    var first = Node{
        .value = 10,
        .next = &second,
    };

    var current: ?*Node = &first;

    while (current) |node| {
        std.debug.print("{d}\n", .{node.value});
        current = node.next;
    }
}
```

The output is:

```text
10
20
30
```

Notice that `current` is optional:

```zig
var current: ?*Node = &first;
```

The loop ends when `current` becomes `null`.

Optional pointers are safer than nullable C pointers because the type system forces the possibility of null to be handled.

In C, this is legal:

```c
int *p = NULL;
printf("%d\n", *p);
```

The program has undefined behavior.

In Zig, a plain pointer cannot hold `null`.

You must write:

```zig
?*i32
```

and unwrap it before dereferencing.

Optional pointers can also be combined with slices:

```zig
?[]u8
```

This means:

> either a slice of bytes, or `null`

This is useful when a buffer may or may not exist.

Exercise 9-11. Write a function that returns a pointer to the largest element in an array.

Exercise 9-12. Modify the linked list example so it computes the sum of all node values.

Exercise 9-13. Why is `?*T` safer than allowing `*T` to contain null silently?

