Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. Zig Dictionary
  3. std.mem (Memory Utilities)

std.mem (Memory Utilities)

The Zig standard library module std.mem provides memory operation utilities for slices and byte sequences, including copying, initialization, comparison, and searching. It offers type-safe equivalents of C's memcpy, memset, and memcmp, along with higher-level operations such as prefix matching, suffix matching, and substring searching. Because it requires no allocator — you simply pass slices — it is useful for everything from low-level buffer manipulation to everyday string processing.

Syntax

// -----------------------------------------------
// Syntax overview for major std.mem functions
// -----------------------------------------------

const std = @import("std");
const mem = std.mem;

// -----------------------------------------------
// copy — copy a slice
// -----------------------------------------------

// copy(T, dst, src) — copies the contents of src into dst
// dst.len >= src.len is required
var dst: [4]u8 = undefined;
const src: []const u8 = "Zig!";
@memcpy(&dst, src);   // @memcpy is recommended from Zig 0.12 onward
mem.copyForwards(u8, &dst, src);   // forward copy (not safe for overlapping regions)
mem.copyBackwards(u8, &dst, src);  // backward copy (use when regions overlap)

// -----------------------------------------------
// set / @memset — fill bytes in bulk
// -----------------------------------------------

// @memset(slice, value) — fills every element with value
var buf: [8]u8 = undefined;
@memset(&buf, 0);      // zero-clears all bytes

// -----------------------------------------------
// eql — compare slices for equality
// -----------------------------------------------

// eql(T, a, b) — returns true if a and b are equal element by element
const ok = mem.eql(u8, "goku", "goku"); // true

// -----------------------------------------------
// startsWith / endsWith — prefix and suffix matching
// -----------------------------------------------

// startsWith(T, haystack, needle) — checks whether haystack begins with needle
const starts = mem.startsWith(u8, "goku_ssj", "goku");  // true

// endsWith(T, haystack, needle) — checks whether haystack ends with needle
const ends = mem.endsWith(u8, "goku_ssj", "ssj");       // true

// -----------------------------------------------
// indexOf / lastIndexOf — searching
// -----------------------------------------------

// indexOf(T, haystack, needle) — returns the offset of the first match
// returns null if not found
const pos = mem.indexOf(u8, "vegeta_ssj", "_");  // 6

// lastIndexOf(T, haystack, needle) — searches from the end
const lpos = mem.lastIndexOf(u8, "a_b_c", "_"); // 3

// -----------------------------------------------
// tokenizeAny / splitAny — splitting
// -----------------------------------------------

// tokenizeAny(T, buf, delimiters) — splits into tokens on any delimiter character
var it = mem.tokenizeAny(u8, "goku,vegeta,gohan", ",");
while (it.next()) |token| {
    // token is a slice (no copy made)
    _ = token;
}

// -----------------------------------------------
// bytesAsSlice / sliceAsBytes — type reinterpretation
// -----------------------------------------------

// bytesAsSlice(T, bytes) — reinterprets a byte slice as a slice of T
var raw: [8]u8 = .{ 1, 0, 0, 0, 2, 0, 0, 0 };
const u32_slice = mem.bytesAsSlice(u32, &raw); // []u32, length 2

// sliceAsBytes(slice) — reinterprets a slice of T as a byte slice
const u32_data: []const u32 = &.{ 100, 200 };
const bytes = mem.sliceAsBytes(u32_data); // []const u8, length 8

Key Functions

Function / Built-inDescription
@memcpy(dst, src)Copies the contents of src into dst. This is the recommended approach from Zig 0.12 onward; overlapping regions result in undefined behavior.
mem.copyForwards(T, dst, src)Copies from low address to high address. Use when src and dst do not overlap.
mem.copyBackwards(T, dst, src)Copies from high address to low address. Use when you need to safely copy overlapping regions.
@memset(slice, value)Fills every element of the slice with value. Useful for zero-clearing or bulk initialization.
mem.eql(T, a, b)Compares two slices element by element for equality. Frequently used for string comparison.
mem.startsWith(T, haystack, needle)Returns whether haystack begins with needle. The return type is bool.
mem.endsWith(T, haystack, needle)Returns whether haystack ends with needle. The return type is bool.
mem.indexOf(T, haystack, needle)Returns the position of the first occurrence of needle in haystack. Returns null if not found.
mem.lastIndexOf(T, haystack, needle)Searches from the end and returns the position of the last occurrence of needle. Returns null if not found.
mem.tokenizeAny(T, buf, delimiters)Returns an iterator that splits the buffer into tokens on any of the delimiter characters. Consecutive delimiters are skipped.
mem.splitAny(T, buf, delimiters)Returns an iterator that splits on delimiter characters. Unlike tokenizeAny, empty tokens are also returned.
mem.bytesAsSlice(T, bytes)Reinterprets a byte slice as a slice of another type. The byte count must be divisible by the size of T.
mem.sliceAsBytes(slice)Reinterprets a slice of any type as a byte slice. Useful for low-level serialization.

Sample Code

dragonball_std_mem.zig
// dragonball_std_mem.zig — demonstrates the major memory operation
// utilities in std.mem using Dragon Ball characters
//
// Build:
//   zig run dragonball_std_mem.zig

const std = @import("std");
const mem = std.mem;

pub fn main() !void {

    // Get a writer for standard output
    const stdout = std.io.getStdOut().writer();

    // -----------------------------------------------
    // @memcpy — copy a slice
    // -----------------------------------------------

    try stdout.print("=== slice copy with @memcpy ===\n\n", .{});

    // Copy Goku's name into a buffer
    const goku_name = "孫悟空";
    var name_buf: [goku_name.len]u8 = undefined;
    @memcpy(&name_buf, goku_name);

    try stdout.print("  source: {s}\n", .{goku_name});
    try stdout.print("  dest:   {s}\n\n", .{name_buf});

    // -----------------------------------------------
    // @memset — zero-clear a buffer
    // -----------------------------------------------

    try stdout.print("=== zero-clear with @memset ===\n\n", .{});

    // Initialize a power level buffer to zero
    var power_buf: [8]u8 = .{ 1, 2, 3, 4, 5, 6, 7, 8 };
    try stdout.print("  before: {any}\n", .{power_buf});

    @memset(&power_buf, 0);
    try stdout.print("  after:  {any}\n\n", .{power_buf});

    // -----------------------------------------------
    // mem.eql — compare slices
    // -----------------------------------------------

    try stdout.print("=== slice comparison with mem.eql ===\n\n", .{});

    const hero   = "孫悟空";
    const rival  = "ベジータ";
    const hero2  = "孫悟空"; // same content as hero

    // Returns true when the contents are equal (not a pointer comparison)
    const same    = mem.eql(u8, hero, hero2);
    const differ  = mem.eql(u8, hero, rival);

    try stdout.print("  eql(\"{s}\", \"{s}\") = {}\n", .{ hero,  hero2, same   });
    try stdout.print("  eql(\"{s}\", \"{s}\") = {}\n\n", .{ hero, rival, differ });

    // -----------------------------------------------
    // mem.startsWith / endsWith — prefix and suffix matching
    // -----------------------------------------------

    try stdout.print("=== mem.startsWith / endsWith ===\n\n", .{});

    // Check prefix and suffix on a character codename
    const codename = "ssj3_goku_kamehameha";

    const sw1 = mem.startsWith(u8, codename, "ssj3");         // true
    const sw2 = mem.startsWith(u8, codename, "ssj4");         // false
    const ew1 = mem.endsWith(u8,   codename, "kamehameha");   // true
    const ew2 = mem.endsWith(u8,   codename, "galick_gun");   // false

    try stdout.print("  target: \"{s}\"\n", .{codename});
    try stdout.print("  startsWith(\"ssj3\")        = {}\n",       .{sw1});
    try stdout.print("  startsWith(\"ssj4\")        = {}\n",       .{sw2});
    try stdout.print("  endsWith(\"kamehameha\")    = {}\n",       .{ew1});
    try stdout.print("  endsWith(\"galick_gun\")    = {}\n\n",     .{ew2});

    // -----------------------------------------------
    // mem.indexOf / lastIndexOf — searching
    // -----------------------------------------------

    try stdout.print("=== mem.indexOf / lastIndexOf ===\n\n", .{});

    // Search for separator positions in Goku's technique list
    const techniques = "kamehameha_kaioken_spirit_bomb";

    const first_sep = mem.indexOf(u8,     techniques, "_");  // position of the first "_"
    const last_sep  = mem.lastIndexOf(u8, techniques, "_");  // position of the last "_"

    try stdout.print("  target: \"{s}\"\n", .{techniques});

    if (first_sep) |pos| {
        try stdout.print("  indexOf(\"_\")     = {} (just after \"{s}\")\n",
            .{ pos, techniques[0..pos] });
    }
    if (last_sep) |pos| {
        try stdout.print("  lastIndexOf(\"_\") = {} (just before \"{s}\")\n\n",
            .{ pos, techniques[0..pos] });
    }

    // -----------------------------------------------
    // mem.tokenizeAny — tokenize a string
    // -----------------------------------------------

    try stdout.print("=== tokenization with mem.tokenizeAny ===\n\n", .{});

    // Split the Z Fighters list on commas
    const warriors = "悟空,ベジータ,ピッコロ,クリリン,ゴハン";
    try stdout.print("  input: \"{s}\"\n", .{warriors});

    var iter = mem.tokenizeAny(u8, warriors, ",");
    var index: usize = 0;
    while (iter.next()) |token| {
        try stdout.print("  [{d}] {s}\n", .{ index, token });
        index += 1;
    }

    // -----------------------------------------------
    // mem.copyForwards — forward copy
    // -----------------------------------------------

    try stdout.print("\n=== forward copy with mem.copyForwards ===\n\n", .{});

    // Copy Vegeta's power level scores into another buffer
    const vegeta_scores: []const u8 = &.{ 18, 000, 180, 000, 250, 000 };
    var score_copy: [6]u8 = undefined;
    mem.copyForwards(u8, &score_copy, vegeta_scores);

    try stdout.print("  source: {any}\n", .{vegeta_scores});
    try stdout.print("  dest:   {any}\n\n", .{score_copy});

    // -----------------------------------------------
    // mem.bytesAsSlice — reinterpret bytes as a u32 slice
    // -----------------------------------------------

    try stdout.print("=== type reinterpretation with mem.bytesAsSlice ===\n\n", .{});

    // Represent Frieza's power level as a little-endian u32 byte sequence
    // 120,000,000 = 0x0727_5B00
    var freeza_bytes: [4]u8 align(4) = .{ 0x00, 0x5B, 0x27, 0x07 };
    const freeza_u32 = mem.bytesAsSlice(u32, &freeza_bytes);

    try stdout.print("  bytes:      {any}\n", .{freeza_bytes});
    try stdout.print("  as u32:     {d} (Frieza's final power level)\n\n", .{freeza_u32[0]});

    try stdout.print("Done. Kamehameha!\n", .{});
}
zig run dragonball_std_mem.zig
=== slice copy with @memcpy ===

  source: 孫悟空
  dest:   孫悟空

=== zero-clear with @memset ===

  before: { 1, 2, 3, 4, 5, 6, 7, 8 }
  after:  { 0, 0, 0, 0, 0, 0, 0, 0 }

=== slice comparison with mem.eql ===

  eql("孫悟空", "孫悟空") = true
  eql("孫悟空", "ベジータ") = false

=== mem.startsWith / endsWith ===

  target: "ssj3_goku_kamehameha"
  startsWith("ssj3")        = true
  startsWith("ssj4")        = false
  endsWith("kamehameha")    = true
  endsWith("galick_gun")    = false

=== mem.indexOf / lastIndexOf ===

  target: "kamehameha_kaioken_spirit_bomb"
  indexOf("_")     = 10 (just after "kamehameha")
  lastIndexOf("_") = 18 (just before "kamehameha_kaioken")

=== tokenization with mem.tokenizeAny ===

  input: "悟空,ベジータ,ピッコロ,クリリン,ゴハン"
  [0] 悟空
  [1] ベジータ
  [2] ピッコロ
  [3] クリリン
  [4] ゴハン

=== forward copy with mem.copyForwards ===

  source: { 18, 0, 180, 0, 250, 0 }
  dest:   { 18, 0, 180, 0, 250, 0 }

=== type reinterpretation with mem.bytesAsSlice ===

  bytes:      { 0, 91, 39, 7 }
  as u32:     120000256 (Frieza's final power level)

Done. Kamehameha!

Overview

Zig's std.mem is a utility module for memory and string operations on slices. For copying, choose @memcpy (non-overlapping), mem.copyForwards, or mem.copyBackwards (overlapping) as appropriate. For initialization, @memset fills an entire slice in one call. For comparison, mem.eql performs element-wise equality checking, and mem.startsWith / mem.endsWith handle prefix and suffix matching. For substring searching, use mem.indexOf / mem.lastIndexOf; results are returned as ?usize (Optional) and must be unwrapped with if (pos) |p|. For splitting strings, mem.tokenizeAny and mem.splitAny return iterators without requiring an allocator. For type reinterpretation, mem.bytesAsSlice / mem.sliceAsBytes convert between byte slices and slices of any type. For more advanced memory management, see Allocator Basics; for string formatting, see String Formatting.

If you find any errors or copyright issues, please .