Lesson 7 of 15

Arrays & Slices

Fixed-Size Arrays and Flexible Slices

Zig provides two closely related sequence types: arrays with a compile-time known length, and slices that represent a view into a contiguous block of memory. Understanding the distinction is essential to writing correct Zig code.

Arrays

An array has a fixed size that is part of its type. [5]u8 is a completely different type from [3]u8. The size is always known at compile time:

// Array literal with explicit type
const a: [5]u8 = .{ 1, 2, 3, 4, 5 };

// The compiler can infer the length
const b = [_]u8{ 10, 20, 30 };

// An array of 100 zeros
const zeros = [_]u8{0} ** 100;

// An array initialized with a fill value
var buf: [256]u8 = undefined;

You access elements with bracket notation, and the length is available through the len field:

const arr = [_]i32{ 10, 20, 30, 40, 50 };
const first = arr[0];        // 10
const length = arr.len;      // 5

Zig performs bounds checking at runtime in safe build modes. Accessing arr[5] on a 5-element array would trigger a panic, not silent undefined behavior.

Think of arrays like the Enterprise's photon torpedo banks --- each slot is indexed, loaded, and ready to fire. Try to access a tube that does not exist and the tactical officer will let you know.

Slices

A slice is a pointer-and-length pair that refers to a portion of an array (or any contiguous memory). The type []const u8 means "a slice of constant bytes." Slices do not own their memory; they borrow it.

const arr = [_]i32{ 1, 2, 3, 4, 5 };

// Slice the entire array
const all: []const i32 = &arr;

// Slice a subrange: indices 1, 2, 3 (end is exclusive)
const middle: []const i32 = arr[1..4];

A mutable slice uses []T instead of []const T:

var data = [_]u8{ 'h', 'e', 'l', 'l', 'o' };
var s: []u8 = &data;
s[0] = 'H';  // modifies the original array

Slice Length

Just like arrays, slices have a len field:

const nums = [_]i32{ 10, 20, 30, 40, 50 };
const s = nums[1..4];
std.debug.print("length: {}\n", .{s.len}); // length: 3

Iterating Over Arrays and Slices

Use a for loop to iterate. You can capture both the element and an optional index:

const items = [_]i32{ 10, 20, 30 };
for (items) |item| {
    std.debug.print("{}\n", .{item});
}

// With index
for (items, 0..) |item, i| {
    std.debug.print("[{}] = {}\n", .{ i, item });
}

Passing Arrays to Functions

Functions typically accept slices rather than fixed-size arrays. This makes them generic over any length:

fn sum(values: []const i32) i32 {
    var total: i32 = 0;
    for (values) |v| {
        total += v;
    }
    return total;
}

To pass an array to a function that takes a slice, use the address-of operator &:

const arr = [_]i32{ 1, 2, 3 };
const result = sum(&arr);

Your Task

Write two functions:

  • sumSlice(values: []const i32) i32 --- returns the sum of all elements in the slice.
  • countNonZero(values: []const i32) usize --- returns the number of elements that are not zero.
Zig runtime loading...
Loading...
Click "Run" to execute your code.