# Tour of `std`

### Tour of `std`

`std` is Zig’s standard library.

A standard library is the set of useful code that comes with the language. You do not need to download it from a package manager. When you install Zig, you already have `std`.

Zig’s official documentation describes the standard library as a collection of commonly used algorithms, data structures, and definitions for building programs and libraries. You can also view the local standard library docs by running `zig std`.

The most common way to use it is:

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

This line means: load the standard library and call it `std` in this file.

After that, you can use things inside it:

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

pub fn main() void {
    std.debug.print("Hello from std!\n", .{});
}
```

Here, `std.debug.print` is a printing function from the standard library.

#### `std` Is Organized into Modules

The standard library is not one giant list of functions. It is organized into modules.

A module is a namespace. It groups related things together.

For example:

```zig
std.debug
```

contains debugging utilities.

```zig
std.mem
```

contains memory helpers.

```zig
std.heap
```

contains allocators.

```zig
std.fs
```

contains file system APIs.

```zig
std.ArrayList
```

is a dynamic array type.

This style keeps names clear. Instead of having a function named `copy` floating around globally, Zig gives you names like:

```zig
std.mem.copyForwards
```

That tells you the function belongs to the memory module.

#### Printing and Debugging

You have already seen:

```zig
std.debug.print("Hello\n", .{});
```

This is useful while learning. It prints text to standard error.

You can also format values:

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

pub fn main() void {
    const age = 30;
    std.debug.print("age = {}\n", .{age});
}
```

The `{}` is a placeholder. The value comes from `.{age}`.

For strings, use `{s}`:

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

pub fn main() void {
    const name = "Zig";
    std.debug.print("Hello, {s}!\n", .{name});
}
```

The output is:

```text
Hello, Zig!
```

This formatting style appears everywhere in Zig. You pass the format string first, then the values as a tuple.

#### Memory Helpers with `std.mem`

`std.mem` contains functions for working with bytes, arrays, and slices.

A slice is a view into a sequence of values. For example, `[]const u8` is often used for text bytes.

Here is a simple comparison:

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

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

    if (std.mem.eql(u8, a, b)) {
        std.debug.print("same\n", .{});
    }
}
```

`std.mem.eql` compares two slices.

The first argument, `u8`, tells Zig the element type. The next two arguments are the values to compare.

This is common in Zig. Many standard library functions ask for the element type explicitly.

#### Allocators with `std.heap`

Zig does not hide heap allocation. When code needs heap memory, it usually receives an allocator.

The standard library gives you allocator implementations in `std.heap`.

A common beginner allocator is the general purpose allocator:

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

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();

    const allocator = gpa.allocator();

    const buffer = try allocator.alloc(u8, 100);
    defer allocator.free(buffer);

    std.debug.print("allocated {} bytes\n", .{buffer.len});
}
```

Read this slowly.

```zig
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
```

This creates an allocator object.

```zig
defer _ = gpa.deinit();
```

This cleans it up at the end of the function.

```zig
const allocator = gpa.allocator();
```

This gets the allocator interface.

```zig
const buffer = try allocator.alloc(u8, 100);
```

This allocates 100 bytes.

```zig
defer allocator.free(buffer);
```

This frees the memory before the function returns.

This is one of Zig’s core habits: allocate explicitly, free explicitly, and use `defer` to keep cleanup close to setup.

#### Dynamic Arrays with `std.ArrayList`

A fixed array has a size known at compile time:

```zig
const numbers = [_]u8{ 1, 2, 3 };
```

But sometimes you need an array that can grow while the program runs. For that, the standard library provides `std.ArrayList`.

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

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();

    const allocator = gpa.allocator();

    var list = std.ArrayList(u32).init(allocator);
    defer list.deinit();

    try list.append(10);
    try list.append(20);
    try list.append(30);

    for (list.items) |value| {
        std.debug.print("{}\n", .{value});
    }
}
```

This creates a dynamic list of `u32` values.

```zig
var list = std.ArrayList(u32).init(allocator);
```

The list needs an allocator because it may grow.

```zig
try list.append(10);
```

Appending may allocate memory, so it may fail. That is why we use `try`.

```zig
defer list.deinit();
```

The list owns memory. It must be cleaned up.

This is the standard pattern for many Zig data structures.

#### File System APIs with `std.fs`

`std.fs` contains APIs for files, directories, and paths.

A simple file read often looks like this:

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

pub fn main() !void {
    const file = try std.fs.cwd().openFile("hello.txt", .{});
    defer file.close();

    var buffer: [1024]u8 = undefined;
    const n = try file.readAll(&buffer);

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

This opens `hello.txt` from the current working directory.

```zig
std.fs.cwd()
```

means “current working directory.”

```zig
openFile("hello.txt", .{})
```

opens the file.

```zig
defer file.close();
```

closes the file when the function exits.

```zig
file.readAll(&buffer)
```

reads bytes into a fixed buffer.

This example avoids heap allocation. The buffer lives on the stack.

#### Formatting with `std.fmt`

Formatting means converting values into text.

You already saw formatting through `std.debug.print`, but the formatting logic itself belongs to `std.fmt`.

For example:

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

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

    const text = try std.fmt.bufPrint(&buffer, "x = {}", .{42});

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

`std.fmt.bufPrint` writes formatted text into a buffer.

It returns a slice containing the written text.

This is useful when you want text as data, not just printed output.

#### Parsing Numbers

The standard library can parse text into numbers.

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

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

    const value = try std.fmt.parseInt(u32, text, 10);

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

The arguments are:

```zig
std.fmt.parseInt(u32, text, 10)
```

`u32` is the output type.

`text` is the input string.

`10` is the base, meaning decimal.

If the text is invalid, parsing returns an error.

#### Hash Maps

A hash map stores key-value pairs.

Zig provides hash maps in the standard library.

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

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();

    const allocator = gpa.allocator();

    var map = std.StringHashMap(u32).init(allocator);
    defer map.deinit();

    try map.put("alice", 10);
    try map.put("bob", 20);

    if (map.get("alice")) |score| {
        std.debug.print("alice = {}\n", .{score});
    }
}
```

`std.StringHashMap(u32)` means: keys are strings, values are `u32`.

Like `ArrayList`, the map needs an allocator because it stores data dynamically.

#### Random Numbers

Random number generation is in `std.Random`.

A small example:

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

pub fn main() void {
    var prng = std.Random.DefaultPrng.init(12345);
    const random = prng.random();

    const value = random.intRangeAtMost(u32, 1, 100);

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

This creates a pseudo-random number generator with a seed.

The same seed gives the same sequence. That is useful for tests.

#### Time

Time utilities live under `std.time`.

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

pub fn main() void {
    const start = std.time.nanoTimestamp();

    var sum: u64 = 0;
    for (0..1_000_000) |i| {
        sum += i;
    }

    const end = std.time.nanoTimestamp();

    std.debug.print("sum = {}\n", .{sum});
    std.debug.print("elapsed ns = {}\n", .{end - start});
}
```

This measures elapsed time in nanoseconds.

This kind of code is useful for simple timing, but real benchmarking needs more care.

#### JSON

Zig’s standard library includes JSON support.

At a high level, JSON work usually means one of two things:

You parse JSON text into values.

You write values as JSON text.

The exact APIs may change across Zig versions, so for serious JSON code, check the standard library docs for your installed compiler version. Zig’s standard library is still evolving before 1.0, and 0.16.0 includes notable standard library changes around I/O.

#### Networking and I/O

The standard library also includes networking and I/O APIs.

This area is important, but it is also one of the more version-sensitive parts of Zig. Zig 0.16.0 has major work around the newer `std.Io` system, so code in older tutorials may not match current APIs.

For beginners, the right approach is:

Learn `std.debug.print`.

Learn file reading and writing.

Learn buffers and slices.

Learn allocators.

Then come back to advanced I/O and networking after the core language feels natural.

#### How to Read `std` Code

Zig’s standard library is written in Zig. That means you can read it.

This is one of the best ways to learn Zig.

When you see:

```zig
std.ArrayList(u8)
```

you can search the standard library source for `ArrayList`.

When you see:

```zig
std.mem.eql
```

you can inspect how equality is implemented.

At first, the code may look dense. That is normal. Read it in small pieces. Focus on function signatures first.

A function signature tells you:

what arguments the function needs

what type it returns

whether it can fail

whether it needs an allocator

whether something happens at compile time

For example:

```zig
pub fn eql(comptime T: type, a: []const T, b: []const T) bool
```

Even before reading the body, you can learn a lot.

It takes a type `T`.

It takes two slices of `T`.

It returns `bool`.

It does not allocate.

It does not return an error.

That is already useful information.

#### The Main Beginner Modules

For now, remember these:

| Module | What it is for |
|---|---|
| `std.debug` | Printing and debugging |
| `std.mem` | Memory and slice helpers |
| `std.heap` | Allocators |
| `std.fs` | Files and directories |
| `std.fmt` | Formatting and parsing text |
| `std.ArrayList` | Dynamic arrays |
| `std.StringHashMap` | String-keyed maps |
| `std.time` | Time and timestamps |
| `std.Random` | Random number generation |
| `std.testing` | Unit tests |

You do not need to memorize the whole standard library.

Instead, learn the pattern:

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

Then learn one module at a time.

#### The Most Important Idea

`std` is not magic.

It is ordinary Zig code bundled with the compiler. It gives you building blocks, but it follows the same rules as your own code.

That means the standard library also teaches the style of Zig:

explicit allocation

visible errors

small functions

clear types

compile-time parameters where useful

direct access to system features

As you learn Zig, you will keep returning to `std`. At first, you use it for printing. Then you use it for files, memory, collections, parsing, testing, networking, and building real programs.

