# Addresses and Pointer Types

### Addresses and Pointer Types

A variable has a value. In Zig, a variable may also have an address.

The address of a value is obtained with `&`.

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

pub fn main() void {
    var x: i32 = 10;
    const p = &x;

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

The expression `&x` means "the address of `x`." The value stored in `p` is a pointer to `x`.

The expression `p.*` means "the value pointed to by `p`." This is called dereferencing the pointer.

The program prints:

```text
10
```

A pointer type is written with `*`.

```zig
*i32
```

This means "pointer to `i32`."

The type of `p` in the previous program is inferred by the compiler. We could write it explicitly:

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

A pointer does not contain an `i32`. It contains the address of an `i32`.

Changing through a pointer changes the original value.

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

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

    p.* = 20;

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

This prints:

```text
20
```

There is only one integer here, `x`. The pointer `p` gives another way to reach it.

Pointers follow the same mutability rule as other Zig values. A `const` pointer binding means the pointer variable cannot be changed to point somewhere else. It does not by itself make the pointed-to value constant.

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

p.* = 20; // ok
```

Here `p` is constant, but `x` is mutable.

A pointer to constant data has a different type:

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

The type `*const i32` means "pointer to constant `i32`." Through this pointer, the value cannot be changed.

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

This distinction is important.

```zig
var x: i32 = 10;

const p: *i32 = &x;        // pointer to mutable i32
const q: *const i32 = &x;  // pointer to constant view of i32
```

Both pointers may refer to the same storage. But `q` does not permit writing through it.

Zig has no implicit pointer dereference for ordinary values. If `p` is a pointer, `p.*` is the value.

```zig
var n: i32 = 7;
const p = &n;

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

This explicitness is deliberate. It keeps address operations visible.

A pointer may be passed to a function.

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

fn increment(p: *i32) void {
    p.* += 1;
}

pub fn main() void {
    var count: i32 = 0;

    increment(&count);
    increment(&count);

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

This prints:

```text
2
```

The function receives a pointer to `count`. It does not receive a copy of the integer. It receives a way to modify the original integer.

Pointers are common when a function must modify a value, avoid copying a large value, or refer to storage whose identity matters.

Zig also permits pointers to structs.

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

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

fn moveRight(p: *Point) void {
    p.x += 1;
}

pub fn main() void {
    var point = Point{ .x = 3, .y = 4 };

    moveRight(&point);

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

This prints:

```text
(4, 4)
```

Notice the field access in `moveRight`:

```zig
p.x += 1;
```

For pointers to structs, Zig allows field access through the pointer. This is equivalent in meaning to accessing the field of the pointed-to struct.

For plain values, dereferencing is explicit:

```zig
p.*
```

For struct fields, the convenient form is used:

```zig
p.x
```

A pointer must point to valid storage. It is an error to keep a pointer to a local variable after that variable is gone.

```zig
fn bad() *i32 {
    var x: i32 = 10;
    return &x; // invalid idea
}
```

The variable `x` belongs to the function call. When the function returns, `x` no longer exists. A pointer to it would be useless and dangerous.

Zig makes many such errors visible. But pointers still require care. They are addresses. They depend on the lifetime, alignment, and mutability of the storage they refer to.

The simplest rule is this: use a pointer only while the pointed-to value is still alive, and write through it only when the pointed-to value is mutable.

Exercise 5-1. Write a function `zero` that takes `*i32` and sets the pointed-to value to zero.

Exercise 5-2. Write a function `swap` that takes two `*i32` values and exchanges the integers they point to.

Exercise 5-3. Declare a `const i32`, take its address, and try to modify it through the pointer. Read the compiler error.

Exercise 5-4. Define a `Rectangle` struct with `width` and `height`, then write a function that doubles both fields through a pointer.

