zig
zig copied to clipboard
Sentinel-terminated array `= undefined` makes sentinel uninitialized
Zig Version
0.12.0-dev.3533+e5d900268
Steps to Reproduce and Observed Behavior
I'm trying to use [32:0]u8 to interop with C. First, I'll show the code that worked for me:
var sha256_1: [33]u8 = undefined;
sha256_1[32] = 0x00;
@breakpoint();
When the breakpoint is hit, memory at the address &sha256_1 obviously looks right:
aa aa aa aa aa aa aa aa ªªªªªªªª
aa aa aa aa aa aa aa aa ªªªªªªªª
aa aa aa aa aa aa aa aa ªªªªªªªª
aa aa aa aa aa aa aa aa ªªªªªªªª
00 .
Now the code that I thought should work the same:
var sha256_1: [32:0]u8 = undefined;
@breakpoint();
but now memory is
aa aa aa aa aa aa aa aa ªªªªªªªª
aa aa aa aa aa aa aa aa ªªªªªªªª
aa aa aa aa aa aa aa aa ªªªªªªªª
aa aa aa aa aa aa aa aa ªªªªªªªª
aa ª
I'm on windows 11 btw
Expected Behavior
I would expect the sentinel to be initialized, just like I did manually in the first snippet. My intuition is that = undefined would not affect the sentinel. This might be a design decision but I haven't found any issue about it. I understand (guess) there might be efficiency reasons to this behaviour, maybe futurely we can include this in docs.
I’m not a Zig expert, so take this with a grain of salt.
My intuition is the opposite. If I initialize the variable to undefined I expect the entire memory region owned by the variable to be undefined. I don’t expect assigning undefined to set any bytes.
You should never read the variable before initializing it with a value and setting the sentinel correctly. If you read the variable before that, the behavior is undefined and so I don’t think it makes sense to complain about it not being null-terminated.
The one thing to check would be making sure that reading a null-terminated-typed-undefined variable has a reasonable error in debug mode.
Initializing an array with this type of pattern is very common, and should not require manually setting the sentinel:
var array: [n:0]u32 = undefined;
for (&array, 0..) |*x, i| {
x.* = @intCast(i);
}
I still wish the semantics in my comment were correct, but I’ve been informed that I was mistaken about how sentinel-terminal-arrays actually work. (In particular, I expected operations on the array, like @silversquirl’s example, to use the sentinel to determine the length, when the compile-time length is used instead.)