# Many-item Pointers

> [*]T: a pointer to an unknown number of items.

```zig
const std = @import("std");
const expect = std.testing.expect;

test "many-item pointers support indexing" {
    var array = [_]u8{ 1, 2, 3, 4 };
    const many: [*]u8 = &array;

    // Indexing and pointer arithmetic are allowed, but there is no `.len`
    // and therefore no bounds checking. You are responsible for the range.
    try expect(many[0] == 1);
    try expect(many[3] == 4);
}

test "convert to a slice by supplying the length" {
    var array = [_]u8{ 1, 2, 3, 4 };
    const many: [*]u8 = &array;

    // The length is the piece of information `[*]T` is missing; adding it
    // back yields a `[]T`, which is bounds-checked again.
    const slice: []u8 = many[0..3];
    try expect(slice.len == 3);
}

test "single-item pointers do not index" {
    // A `*T` is one item. `ptr[1]` is a compile error, which is the whole
    // reason Zig distinguishes `*T` from `[*]T` where C has only `T*`.
    var x: u8 = 9;
    const single: *u8 = &x;
    try expect(single.* == 9);
}
```

*Runnable: compiled to WebAssembly and executed by CI against Zig master. (`02-language.many-item-pointers`)*

C has one pointer type, `T*`, which is used for three different things: one
item, many items, and "maybe nothing". Zig splits them apart:

| Zig | Meaning |
| --- | --- |
| `*T` | exactly one `T` |
| `[*]T` | many `T`, count unknown |
| `[]T` | many `T`, count known (a [slice](https://www.ziglang.in/learn/language-basics/slices/)) |
| `?*T` | one `T`, or nothing |

## What `[*]T` gives up

A many-item pointer supports indexing and pointer arithmetic, but has no `.len`
and therefore **no bounds checking**. It exists mainly for C interop and for
implementing the safe abstractions on top.

The moment you know the length, convert to a slice:

```zig
const slice: []u8 = many[0..count];
```

That single step buys back bounds checks, `for` iteration, and `.len`. Prefer
slices everywhere except the boundary where a length genuinely is not available.

Correspondingly, `*T` deliberately does *not* support indexing: `ptr[1]` on a
single-item pointer is a compile error, catching a class of C bug at the type
level.
