Greetings. I figured that this Zig code will compile fine:
const std = @import("std");
pub fn main() !void {
const arr = try std.heap.page_allocator.alloc(usize, 3);
@memcpy(arr, &.{ 1, 2, 3 });
}
However, I get this compile error:
test.zig:5:18: error: type '*const struct { comptime comptime_int = 1, comptime comptime_int = 2, comptime comptime_int = 3 }' is not an indexable pointer
@memcpy(arr, &.{ 1, 2, 3 });
^~~~~~~~~~~~~
test.zig:5:18: note: operand must be a slice, a many pointer or a pointer to an array
Am I doing something wrong?
I think Zig thinks that the slice is an anonymous struct? Can’t it infer the type from the destination?
You can give the array an explicit type while still inferring the length (and getting a pointer to it) like so:
&[_]usize{ 1, 2, 3 }
2 Likes
The parameters of @memcpy
don’t have a concrete result type, they simply keep the type of the value you pass in (like anytype
parameters). The expression .{ 1, 2, 3 }
will always resolve to a tuple if it has no result type, so &.{ 1, 2, 3 }
resolves to a pointer to a tuple.
If you instead did @as([]const usize, &.{ 1, 2, 3 })
, the following would hold true:
- With a result type of
[]const usize
, &.{ 1, 2, 3 }
must take the form of &x
, where x
is an array of usize
, meaning the result type of .{ 1, 2, 3 }
is [3]usize
.
- Since the result type of
.{ 1, 2, 3 }
is an array, each element in .{ 1, 2, 3 }
is coerced to an element in the array, and since comptime_int
can coerce to any integer type, each element of .{ 1, 2, 3 }
successfully coerces to a usize
.
- After the
[3]usize
is successfully initialized, its pointer is taken with &
, yielding *const [3]usize
, which then coerces to the final result of []const usize
.
https://ziglang.org/documentation/master/#Result-Locations
2 Likes
const std = @import("std");
pub fn main() !void {
const arr = try std.heap.page_allocator.create([3]usize);
arr.* = .{ 1, 2, 3 };
}
7 Likes