I’m very new to Zig – I’m using it (for the first time) to work through the Advent Of Code problems.
As part of testing my solution to the the linked problem, I’m trying to create a struct containing an array created from an literal, but I’m getting an error that I can’t resolve:
const std = @import("std");
const print = std.debug.print;
const Update = struct { values: []u32 };
test "Create and operate on an Update" {
const update = Update{ .values = [3]u32{ 1, 2, 3 } };
print("DEBUG - update is {}n", .{update});
}
$ zig test scratch.zig
scratch.zig:7:40: error: array literal requires address-of operator (&) to coerce to slice type '[]u32'
const update = Update{ .values = [3]u32{ 1, 2, 3 } };
~~~~~~~~~~~~^~~~~~~~~~~~~~~
That seems clear enough – except that when I follow the advice, I get a type-mismatch:
const update = Update{ .values = &[3]u32{ 1, 2, 3 } };
$ zig test scratch.zig
scratch.zig:7:29: error: expected type '[]u32', found '*const [3]u32'
const update = Update{ .values = &[3]u32{ 1, 2, 3 } };
~^~~~~~~~~~~~~~~~~~~~~~~~~~~
That makes sense – so far as I can understand, &
converts a variable to a pointer, so it’s correct for the compiler to complain about being passed a *[]u32
when it expects a []u32
. So, both options give me an error – how can I pass a []u32
to the Update
constructor?
EDIT – after reading this article, I think I have a better idea of what’s going on:
[]u32
is a slice ofu32
s, not an array thereof.- Which is correct for what I want – because an array must have a comptime-defined size, which would imply that all
Update
s much havevalues
of the same size.
- Which is correct for what I want – because an array must have a comptime-defined size, which would imply that all
- So I need to instantiate an
Update
like so:
const Update = struct { values: []u32 };
test "Create and operate on an Update" {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var values = try allocator.alloc(u32, 3);
defer allocator.free(values);
values[0] = 1;
values[1] = 2;
values[2] = 3;
const update = Update{ .values = values };
print("DEBUG - update is {}n", .{update});
}
Which works as-expected. Is this the idiomatic way to do this? I’m surprised there’s no built-in way to define a “slice-literal” as there is for arrays – 5+n lines to define an n-length slice (or 3+n lines if you already have an allocator available) seems verbose, to me!