#How to initialise a slice field of a struct
1 messages · Page 1 of 1 (latest)
Because slice is a pointer type, you can't directly assign array to it. so assigning reference of array works, but since the array is a literal it has to be const
Firstly, a slice is just a ptr + len - it can't directly hold the array. That's why you needed the address of operator (to coerce it).
Secondly, Zig literals are always const (I think they're stored directly in the .data section so you can't modify them?).
var arr = [_]u8{1, 2};
const slice: []u8 = &arr;
This would work tho
Thanks, I think I understand a bit better now.
Say that MyStruct is being constructed in a function called MyFunc. I give it a slice which is just a pointer to some array literal in MyFn.
First, provided that the slice is defined as const in the definition of MyStruct, I can do
const baz: MyStruct = .{
.foo = 1,
.bar = &.{some_runtime_var, some_other_runtime_var),
};
If the array literal is stored in the .data section and cannot be changed, how can I set the values in it to something only known at runtime.
Second, what happens if I am in MyFunc, set my variable baz as above, recursively call MyFunc with different parameters, return from that recursive call and check the value of baz.bar. If there is truly a single array literal in the .data section (or something), how can the recursive call set the values of that array to some other runtime values but I still have the same values in baz (from the first MyFunc call) after the recursive call returns? Are they some how restored?
Here is a program to demonstrate
const MyStruct = struct {
bar: []const u8,
};
fn MyFunc(x: u8, y: u8, recurse: bool) void {
const baz: MyStruct = .{
.bar = &.{ x, y },
};
if (recurse)
MyFunc(x + 1, y + 1, false);
std.debug.print("{} {}\n", .{ baz.bar[0], baz.bar[1] });
}
pub fn main() !void {
var it = std.process.args();
_ = it.next();
while (it.next()) |i_s| {
const i = try std.fmt.parseInt(u8, i_s, 10);
MyFunc(i + 1, i, true);
}
}
If you pass it the value 1 on the command line, it outputs
3 2
2 1
Which shows a runtime value being inserted into the literal array and that the values 2 and 1 are "restored" after the recursive call.
I feel like I muddied the waters a bit by mentioning that, sorry.
When I say literal I mean something like this (strings are the usual example)
const array1 = "Hello" //*const [5:0]u8
In this case it is stored in the .data section like I said, I'm certain
The arrays in your example are, firstly, not literals. Literals are known at compile time, they're the 'literal' characters/values in the source file. X and Y are runtime values provided as parameters into MyFunc. When I say literals go in the .data section I don't mean the compiler just makes space there for them (although it does have to do that), I mean the actual values from the source file go in there. There are no "actual values" in your example because the compiler has no idea what they could be.
I'm actually not certain if it was correct to say that the array in your original example was a literal (literal strings definitely are but I'm unsure for literal arrays that aren't explicitly strings), sorry! But what I am more certain about is that the reason both the original example and your new example still requires the field slice to have the const modifier (despite your example not having a literal) is that creating the array like that creates a temporary value, and temporary values are always const in Zig (and thus any pointer to them is *const). This is why Cipharius' example above works, because assigning the value to the var arr means it is no longer a temporary.
Thanks, I think that the temporary value bit was the key thing I was missing