# Pointer Arithmetic

### Pointer Arithmetic

Pointer arithmetic means forming a new pointer by moving from one element to another.

In Zig, ordinary single-item pointers do not support pointer arithmetic.

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

// p + 1 is not the right operation here
```

The type `*i32` means one `i32`. There is no second item promised by the type.

Many-item pointers do support pointer arithmetic.

```zig
var items = [_]i32{ 10, 20, 30 };
const p: [*]i32 = &items;

const q = p + 1;
```

The pointer `q` points one element after `p`.

```zig
q[0] // same as p[1]
```

Here is a complete program.

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

pub fn main() void {
    var items = [_]i32{ 10, 20, 30 };

    const p: [*]i32 = &items;
    const q = p + 1;

    std.debug.print("{d}\n", .{q[0]});
}
```

It prints:

```text
20
```

The addition is measured in elements, not bytes. Since `p` points to `i32`, `p + 1` moves by one `i32`.

Subtraction works in the same way.

```zig
const r = q - 1;
```

Now `r` points to the same item as `p`.

Pointer arithmetic does not carry bounds. If `p` points to the first element of a three-element array, then `p + 3` points just past the last element. It must not be read as an item.

```zig
const end = p + 3;

// end[0] is outside the array
```

A pointer past the end may be useful as a marker. It is not a pointer to a valid element.

Because many-item pointers do not store a length, the program must know the bounds by some other means.

```zig
fn printMany(ptr: [*]const i32, len: usize) void {
    var i: usize = 0;

    while (i < len) : (i += 1) {
        std.debug.print("{d}\n", .{ptr[i]});
    }
}
```

The pointer alone is not enough. The length is a separate argument.

Slices make this safer.

```zig
fn printSlice(items: []const i32) void {
    for (items) |item| {
        std.debug.print("{d}\n", .{item});
    }
}
```

A slice contains both pointer and length. Most ordinary Zig code should use a slice instead of doing pointer arithmetic.

Pointer arithmetic is mainly useful near low-level interfaces: C APIs, manual memory handling, device buffers, and algorithms that are written directly over raw memory.

A byte pointer is often used when the program wants to move by bytes.

```zig
var bytes = [_]u8{ 1, 2, 3, 4 };
const p: [*]u8 = &bytes;

const second = p + 1;
```

Here `second` points to the second byte.

For a larger type, pointer movement is still by elements.

```zig
var nums = [_]u32{ 1, 2, 3 };
const p: [*]u32 = &nums;

const next = p + 1;
```

`next` points to the second `u32`, not the next byte.

Indexing is often clearer than addition.

```zig
p[2]
```

This means the same item as:

```zig
(p + 2)[0]
```

Prefer the first form unless the pointer itself must move.

A common pattern is to advance a pointer while a count decreases.

```zig
fn sumMany(ptr: [*]const i32, len: usize) i32 {
    var p = ptr;
    var n = len;
    var total: i32 = 0;

    while (n != 0) : ({
        p += 1;
        n -= 1;
    }) {
        total += p[0];
    }

    return total;
}
```

This works, but the slice version is usually better.

```zig
fn sumSlice(items: []const i32) i32 {
    var total: i32 = 0;

    for (items) |item| {
        total += item;
    }

    return total;
}
```

The slice version says less about addresses and more about the data.

Pointer arithmetic can also be used with sentinel pointers.

```zig
fn lenZ(ptr: [*:0]const u8) usize {
    var p = ptr;
    var n: usize = 0;

    while (p[0] != 0) : ({
        p += 1;
        n += 1;
    }) {}

    return n;
}
```

The sentinel value `0` marks the end. The pointer moves one byte at a time until that value is found.

This is the shape of many C string operations. Zig can express it, but ordinary Zig strings are usually slices:

```zig
[]const u8
```

A slice already has a length, so no sentinel scan is needed.

Pointer arithmetic is a low-level operation. It is useful when the type and the surrounding code provide enough information to prove that the movement is valid.

The rule is simple: move only inside storage that really contains adjacent elements, and never read outside the valid range.

Exercise 5-17. Create an array of four integers and use a many-item pointer to print the second and third elements.

Exercise 5-18. Write `sumMany` using pointer arithmetic and a length.

Exercise 5-19. Rewrite `sumMany` using a slice.

Exercise 5-20. Write a function that counts bytes in a `[*:0]const u8` until it reaches the zero sentinel.

