# `std.mem`

### `std.mem`

The `std.mem` module contains operations on memory, slices, bytes, and basic data movement. Much of Zig programming eventually passes through `std.mem`.

A simple example copies bytes from one array into another.

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

pub fn main() void {
    var source = [_]u8{ 1, 2, 3, 4 };
    var dest = [_]u8{ 0, 0, 0, 0 };

    @memcpy(dest[0..], source[0..]);

    std.debug.print("{any}\n", .{dest});
}
```

The output is:

```text
{ 1, 2, 3, 4 }
```

Slices are central to `std.mem`.

A slice is a pointer and a length:

```zig
[]u8
```

This means: “a runtime-sized slice of writable bytes.”

A constant slice is:

```zig
[]const u8
```

Many functions in `std.mem` operate on slices rather than raw pointers.

A string in Zig is usually a slice of bytes:

```zig
const message = "hello";
```

The type is:

```zig
*const [5:0]u8
```

but it automatically coerces to:

```zig
[]const u8
```

when needed.

A common operation is comparing slices.

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

pub fn main() void {
    const a = "zig";
    const b = "zig";

    const equal = std.mem.eql(u8, a, b);

    std.debug.print("{any}\n", .{equal});
}
```

The output is:

```text
true
```

`std.mem.eql` compares elements one by one.

The first argument is the element type:

```zig
u8
```

This tells Zig how to compare the slice contents.

Searching slices is also common.

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

pub fn main() void {
    const text = "hello zig";

    if (std.mem.indexOf(u8, text, "zig")) |index| {
        std.debug.print("found at {d}\n", .{index});
    }
}
```

The output is:

```text
found at 6
```

`indexOf` returns an optional value.

If the substring exists, the index is returned.

If not, the result is `null`.

Many `std.mem` functions follow this style.

Memory initialization is another common task.

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

pub fn main() void {
    var buffer: [8]u8 = undefined;

    @memset(buffer[0..], 0);

    std.debug.print("{any}\n", .{buffer});
}
```

The output is:

```text
{ 0, 0, 0, 0, 0, 0, 0, 0 }
```

`undefined` means the memory initially contains unspecified values.

Zig does not automatically clear memory.

This avoids hidden work and keeps costs visible.

`@memset` explicitly fills memory with a value.

Slices can also be split.

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

pub fn main() void {
    const text = "abcdef";

    const left = text[0..3];
    const right = text[3..];

    std.debug.print("{s}\n", .{left});
    std.debug.print("{s}\n", .{right});
}
```

The output is:

```text
abc
def
```

Slicing does not allocate memory.

The slices point into the original data.

Many operations in Zig avoid allocation unless explicitly requested.

`std.mem` also provides functions for byte order conversion, alignment calculations, tokenization, and parsing support.

For example:

| Function | Purpose |
|---|---|
| `std.mem.eql` | Compare slices |
| `std.mem.indexOf` | Search slices |
| `std.mem.startsWith` | Prefix check |
| `std.mem.endsWith` | Suffix check |
| `std.mem.splitSequence` | Split slices |
| `std.mem.trim` | Remove bytes from edges |
| `std.mem.concat` | Concatenate with allocation |

A tokenizer example:

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

pub fn main() void {
    const text = "red,green,blue";

    var it = std.mem.splitSequence(u8, text, ",");

    while (it.next()) |part| {
        std.debug.print("{s}\n", .{part});
    }
}
```

The output is:

```text
red
green
blue
```

The iterator returns slices into the original string.

No copying occurs.

This is typical Zig design: explicit allocation, direct memory access, and predictable cost.

Exercise 14-5. Compare two strings with `std.mem.eql`.

Exercise 14-6. Search for a substring with `std.mem.indexOf`.

Exercise 14-7. Write a tokenizer that splits words separated by spaces.

Exercise 14-8. Allocate an array, fill it with a value using `@memset`, and print the result.

