# Optionals

> Zig's answer to null, checked by the compiler.

A `?T` holds either a `T` or `null`. The compiler will not let you use the
value without handling the `null` case first, so there is no such thing as an
accidental null dereference.

These are real tests. Run executes the actual `zig test` runner, compiled to
WebAssembly.

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

test "optional payload capture" {
    var maybe: ?i32 = null;
    try expect(maybe == null);

    maybe = 42;
    if (maybe) |value| {
        try expect(value == 42);
    } else {
        unreachable;
    }
}

test "orelse supplies a default" {
    const nothing: ?u32 = null;
    try expect((nothing orelse 7) == 7);
}

test "optional pointers are free" {
    // A `?*T` is the same size as a `*T`; null is the 0 address.
    try expect(@sizeOf(?*i32) == @sizeOf(*i32));
}
```

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

## Payload capture

The `if (maybe) |value|` form is *payload capture*: inside the block, `value` is
a plain `i32`, not an optional. The unwrapping and the null check are the same
piece of syntax, so they cannot drift apart.

`orelse` is the shorthand when all you want is a fallback:

```zig
const port = maybe_port orelse 8080;
```

## Optional pointers are free

`?*T` is the same size as `*T`. Zig uses the null address as the `null` tag, so
optional pointers cost nothing: no extra byte, no wrapper struct. The last test
above asserts exactly this with `@sizeOf`.

Note that this only applies to pointers. A `?u32` genuinely needs a tag byte
alongside the payload, because every `u32` bit pattern is a valid `u32`.
