Slices

Slices are Zig’s way to represent a variable-length sequence.

const std = @import("std");
const expectEqual = std.testing.expectEqual;

test "creating a slice" {
    // We can create a slice from an array.
    const a = [_]u64{ 1, 2, 3, 4, 5 };
    const s: []const u64 = &a;
    try expectEqual(5, s.len);

    // Constant slices can be initialized directly.
    const t: []const u64 = &.{ 1, 2, 3, 4, 5 };
    try expectEqual(5, t.len);
}

test "slice indexing" {
    // Access elements with […].
    var a = [5]u64{ 1, 2, 3, 4, 5 };
    var slice: []u64 = &a;
    try expectEqual(5, slice[4]);

    slice[4] *= 2;
    try expectEqual(10, slice[4]);
}

test "slicing" {
    // Use slicing syntax to create a slices that points
    // to part of an array.
    const a = [_]u64{ 1, 2, 3, 4, 5 };
    const s = a[1..4];
    try expectEqual(3, s.len);
    try expectEqual(2, s[0]);
    try expectEqual(3, s[1]);
    try expectEqual(4, s[2]);

    // Slice a slice.
    const t = s[1..2];
    try expectEqual(1, t.len);
    try expectEqual(3, t[0]);
}
$ zig test slices-1.zig
All 3 tests passed.

At runtime, a slice consists of a pointer to the first element and a length. We can access these fields directly with .ptr and .len:

const std = @import("std");
const expectEqual = std.testing.expectEqual;

test "slice representation" {
    const a = [_]u64{ 1, 2, 3, 4, 5 };
    const s = a[1..4];
    try expectEqual(
        @intFromPtr(&a[1]),
        @intFromPtr(s.ptr),
    );
    try expectEqual(3, s.len);
}
$ zig test slices-2.zig
All 1 tests passed.

Next example: Pointers.