Skip to main content

Standard Library Overview

Zig’s standard library (std) provides a comprehensive set of modules for building robust, portable applications. The standard library is designed to be minimal, explicit, and platform-agnostic while providing powerful abstractions for common programming tasks.

Importing the Standard Library

All Zig programs import the standard library through a consistent pattern:
const std = @import("std");
From there, you can access any module through the std namespace:
const std = @import("std");
const Allocator = std.mem.Allocator;
const ArrayList = std.ArrayList;
const testing = std.testing;

Library Organization

The standard library is organized into logical modules, each serving a specific domain. Here’s how the library is structured:

Core Modules

mem

Memory management, allocators, and memory utilities

heap

Heap allocator implementations (Arena, Page, Debug)

fs

File system operations and directory management

os

Operating system interfaces and syscalls

Data Structures

ArrayList

Dynamic, growable arrays

HashMap

Hash-based key-value storage

ArrayHashMap

Iteration-order-preserving hash maps

LinkedList

Singly and doubly linked lists

Format and Parsing

fmt

String formatting and parsing

json

JSON parsing and stringification (RFC 8259)

base64

Base64 encoding and decoding

unicode

Unicode utilities and UTF-8/UTF-16 handling

Main Exports from std.zig

The main std.zig file re-exports commonly used types and modules:
lib/std/std.zig
// Data structures
pub const ArrayList = array_list.Aligned;
pub const ArrayHashMap = array_hash_map.ArrayHashMap;
pub const HashMap = hash_map.HashMap;
pub const AutoHashMap = hash_map.AutoHashMap;
pub const StringHashMap = hash_map.StringHashMap;

// Linked lists
pub const DoublyLinkedList = @import("DoublyLinkedList.zig");
pub const SinglyLinkedList = @import("SinglyLinkedList.zig");

// Collections
pub const PriorityQueue = @import("priority_queue.zig").PriorityQueue;
pub const Deque = @import("deque.zig").Deque;
pub const BitStack = @import("BitStack.zig");

// Bit sets
pub const DynamicBitSet = bit_set.DynamicBitSet;
pub const StaticBitSet = bit_set.StaticBitSet;

// System types
pub const Thread = @import("Thread.zig");
pub const Random = @import("Random.zig");
pub const Uri = @import("Uri.zig");
Many types have both managed and unmanaged variants (e.g., HashMap and HashMapUnmanaged). Unmanaged versions don’t store the allocator, requiring it to be passed to each method.

Standard Library Options

You can customize standard library behavior via std_options in your root file:
root.zig
pub const std_options = .{
    // Logging configuration
    .log_level = .info,
    .logFn = myCustomLogFunction,
    
    // Memory configuration
    .page_size_min = 4096,
    .page_size_max = 16384,
    
    // Formatting
    .fmt_max_depth = 5,
    
    // HTTP configuration
    .http_disable_tls = false,
    .http_enable_ssl_key_log_file = true,
    
    // Stack tracing
    .allow_stack_tracing = true,
};

Available Options

lib/std/std.zig:114-176
pub const Options = struct {
    enable_segfault_handler: bool = debug.default_enable_segfault_handler,
    
    wasiCwd: fn () os.wasi.fd_t = fs.defaultWasiCwd,
    
    // Logging
    log_level: log.Level = log.default_level,
    log_scope_levels: []const log.ScopeLevel = &.{},
    logFn: fn (
        comptime message_level: log.Level,
        comptime scope: @EnumLiteral(),
        comptime format: []const u8,
        args: anytype,
    ) void = log.defaultLog,
    
    // Memory
    page_size_min: ?usize = null,
    page_size_max: ?usize = null,
    queryPageSize: fn () usize = heap.defaultQueryPageSize,
    
    // Formatting
    fmt_max_depth: usize = fmt.default_max_depth,
    
    // Cryptography
    cryptoRandomSeed: fn (buffer: []u8) void = @import("crypto/tlcsprng.zig").defaultRandomSeed,
    crypto_always_getrandom: bool = false,
    crypto_fork_safety: bool = true,
    
    // HTTP
    http_disable_tls: bool = false,
    http_enable_ssl_key_log_file: bool = @import("builtin").mode == .Debug,
    
    side_channels_mitigations: crypto.SideChannelsMitigations = crypto.default_side_channels_mitigations,
    
    // Stack tracing
    allow_stack_tracing: bool = !@import("builtin").strip_debug_info,
};
The std_options override is checked at compile time, allowing the standard library to adapt to your specific requirements without runtime overhead.

Module Categories

Memory Management

  • std.mem - Memory utilities, comparison, and the Allocator interface
  • std.heap - Heap allocator implementations

System Interaction

  • std.os - Low-level operating system APIs
  • std.posix - POSIX-compliant system calls
  • std.fs - File system operations
  • std.process - Process management and environment variables

Data Structures & Algorithms

  • std.ArrayList - Dynamic arrays
  • std.HashMap, std.ArrayHashMap - Hash maps
  • std.sort - Sorting algorithms
  • std.PriorityQueue - Priority queue implementation

Text Processing

  • std.fmt - String formatting and parsing
  • std.ascii - ASCII character utilities
  • std.unicode - Unicode operations
  • std.json - JSON parsing and serialization

Cryptography & Hashing

  • std.crypto - Cryptographic primitives
  • std.hash - Hash functions
  • std.Random - Random number generation

Debugging & Testing

  • std.debug - Debug utilities and stack traces
  • std.testing - Testing framework and assertions
  • std.log - Structured logging

Networking & I/O

  • std.http - HTTP client implementation
  • std.Io - I/O abstractions (Reader, Writer)
  • std.net - Network operations

Build System

  • std.Build - Build system API
  • std.Target - Target platform information
  • std.SemanticVersion - Semantic versioning

Common Patterns

Using Allocators

Most standard library types require an allocator:
const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();
    
    // Create dynamic array
    var list = std.ArrayList(i32).init(allocator);
    defer list.deinit();
    
    try list.append(42);
}

Error Handling

Zig uses explicit error handling throughout the standard library:
const std = @import("std");

pub fn readConfig(allocator: std.mem.Allocator, path: []const u8) ![]u8 {
    const file = try std.fs.cwd().openFile(path, .{});
    defer file.close();
    
    return try file.readToEndAlloc(allocator, 1024 * 1024);
}

Testing

The standard library provides a comprehensive testing framework:
const std = @import("std");
const testing = std.testing;

test "basic addition" {
    try testing.expectEqual(4, 2 + 2);
}

test "string equality" {
    try testing.expectEqualStrings("hello", "hello");
}

Platform Support

The standard library is designed to work across all Zig-supported platforms:
  • Desktop: Linux, Windows, macOS
  • Mobile: iOS, Android (via Zig’s cross-compilation)
  • Embedded: Freestanding, various microcontrollers
  • Web: WebAssembly (WASI)
Platform-specific code is isolated behind consistent interfaces. The standard library uses compile-time introspection (@import("builtin")) to adapt to the target platform.

Next Steps

Allocators

Deep dive into Zig’s memory allocator system

Testing Framework

Learn about testing and assertions

Key Modules

Explore the most important standard library modules

Build System

Understand the Zig build system

Build docs developers (and LLMs) love