I've successfully passed iterable 1d arrays into a function like this
const std = @import("std");
pub fn loopArray(arr: []u8) void {
for (arr, 0..) |elem, i| {
std.debug.print("array at {d} = {d}", .{ i, elem });
}
}
var foo: [4]u8 = .{ 4, 3, 2, 8 };
pub fn main() void {
loopArray(&foo);
}
but when I try to extend it to multiple dimensions
pub fn loopArray2(arr: [][]u8) void {
for (arr, 0..) |row, j| {
for (row, 0..) |elem, i| {
std.debug.print("array at {d},{d} = {d}", .{ j, i, elem });
}
}
}
var foo: [4]u8 = .{ 4, 3, 2, 8 };
var bar: [2][4]u8 = .{ .{ 4, 3, 2, 8 }, .{ 4, 3, 2, 8 } };
pub fn main() void {
loopArray2(&bar);
}
i get this error:
arrayLoop.zig:21:16: error: expected type '[][]u8', found '*[2][4]u8'
loopArray2(&bar);
one way I managed to do this is by marking it as anytype but that's not ideal as I want stricter typing on my function
pub fn loopArray2(arr: anytype) void {
for (arr, 0..) |row, j| {
for (row, 0..) |elem, i| {
std.debug.print("array at {d},{d} = {d}", .{ j, i, elem });
}
}
}
This is because of the difference between
[n]u8, a value type and[]u8, a slice type representing a pointer and a length.[2][4]u8represents a single contiguous region of memory 8 bytes long.[][]u8represents a slice of slices where each slice contains a pointer and a length. A slice is equivalent tostruct {ptr: [*]u8, len: usize}.[*]u8is an indexable pointer with an unknown length.You can solve it by making an array of slices, like this:
This will no longer be a contiguous region of memory like
[2][4]u8is, instead it is a two-len slice holding two four-len slices.If you want a contiguous region of memory, you can simulate a 2d array with a 1d array (ie
const bar: [8]u8 = .{4, 3, 2, 8, 4, 3, 2, 8};)