-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
translate-c: negative array indices don't work #8556
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
See #1738 |
I'm running into a variation of this issue. This time using
This C code: static const int bid_breakpoints_binary32[] = { 1,2,3,4 };
int main() {
int index = -80;
int m_min = (bid_breakpoints_binary32 + 80)[index];
return 0;
} Generates this zig code pub const bid_breakpoints_binary32: [4]c_int = [4]c_int{
1,
2,
3,
4,
};
pub export fn main() c_int {
var index: c_int = -@as(c_int, 80);
var m_min: c_int = @ptrCast([*c]const c_int, @alignCast(@alignOf(c_int), &bid_breakpoints_binary32)) + @bitCast(usize, @intCast(isize, @as(c_int, 80)))[@intCast(c_uint, index)];
return 0;
} Which gives this error
Part of the problem I think is that a surrounding pair of parentheses is dropped. Additionally the index is negative, which will later fail with the message in the original post:
|
How about if (bar[-%@as(usize, 1)] != @as(c_int, 1)) { or (because unary -% currently seems not to work (see #8574, also #1770, #7951)) if (bar[@as(usize, 0) -% 1] != @as(c_int, 1)) { Arithmetic with unsigned integers in C is modular arithmetic so all arithmetic operators should be translated as +%, -% *% anyway. |
That would work if it's known at compile time but it won't work for runtime negative integers. |
I think for signed integer variables, var index : c_int = -1000; should work because in C (assuming sizeof(void*) == sizeof(long)) if given struct foo* bar; then &bar[ index] == bar + index where in the third line all arithmetic is modular (aka wrapping). IMHO this would be more natural if Zig had modular integers (see #7512) because that is what really going on here. |
Uh... At least with Windows (P64, not LP64), (Edit) I think you need to use |
Take advantage of wrapping pointer arithmetic to enable negative array subscripts. Fixes ziglang#8556
A rather complicated workaround for handling signed array subscripts. Once `[*]T + isize` is allowed, this can be removed. Fixes ziglang#8556
A rather complicated workaround for handling signed array subscripts. Once `[*]T + isize` is allowed, this can be removed. Fixes ziglang#8556
A rather complicated workaround for handling signed array subscripts. Once `[*]T + isize` is allowed, this can be removed. Fixes ziglang#8556
A rather complicated workaround for handling signed array subscripts. Once `[*]T + isize` is allowed, this can be removed. Fixes ziglang#8556
A rather complicated workaround for handling signed array subscripts. Once `[*]T + isize` is allowed, this can be removed. Fixes #8556
In C, array indexing is just shorthand for pointer arithmetic, but in Zig array subscripts are required to be unsigned. That means any C code which uses a negative array index (uncommon, but legal) can't be translated directly to a Zig array indexing operation.
From the C standard
The if statement in this valid C code
produces this line when translated (
error: attempt to cast negative value to unsigned integer
):One solution would be to always translate C array index operations to Zig pointer arithmetic:
or bitcast indices to
usize
:Which is pretty ugly but I think guaranteed to work.
Happy to implement either solution (or something better if there are other ideas) if people think it's worthwhile.
The text was updated successfully, but these errors were encountered: