C arrays allow for negative indexing
Not really. Array indexing boils down to pointer arithmetic with the additive (+ and -) operators. From C17 6.5.6/8 emphasis mine:
If the pointer operand points to an element of
an array object, and the array is large enough, the result points to an element offset from
the original element such that the difference of the subscripts of the resulting and original
array elements equals the integer expression.
...
If both the pointer
operand and the result point to elements of the same array object, or one past the last
element of the array object, the evaluation shall not produce an overflow; otherwise, the
behavior is undefined.
The reason why -
is allowed in the first place is because it can be useful for calculating a relative offset based on a certain index. But the offset still has to end up pointing at an item inside the array, or you invoke undefined behavior.
Your struct example actually does just that - there is no guarantee that those two arrays are allocated adjacently (even though it is very likely). The compiler is free to insert padding in between the two arrays. Also the compiler is free to assume that arr1
is never modified in case we do foo.arr2[-2]=3;
.
This code could in theory print 2 2 2:
std::cout << foo.arr2[-2] << std::endl;
std::cout << foo.arr1[1] << std::endl; // store foo.arr1[1] in a register
foo.arr2[-2]=3;
std::cout << foo.arr1[1] << std::endl; // print once more using that same register