Reputation: 105
Consider the following code:
int data[2][2];
int* p(&data[0][0]);
p[3] = 0;
Or equivalently:
int data[2][2];
int (&row0)[2] = data[0];
int* p = &row0[0];
p[3] = 0;
It's not clear to me whether this is undefined behaviour or not.
p
is a pointer to the first element of an array row0
with 2 elements, therefore p[3]
accesses past the end of the array, which is UB according to 7.6.6 [expr.add]:
- When an expression J that has integral type is added to or subtracted from an expression P of pointer type, the result has the type of P.
- If P evaluates to a null pointer value and J evaluates to 0, the result is a null pointer value.
- Otherwise, if P points to element
x[i]
of an array objectx
withn
elements, the expressions P + J and J + P (where J has the valuej
) point to the (possibly-hypothetical) elementx[i+j]
if 0 ≤i + j
≤n
and the expression P - J points to the (possibly-hypothetical) elementx[i−j]
if 0 ≤i − j
≤n
.- Otherwise, the behavior is undefined.
I don't see anything in the standard that gives special treatment to multidimensional arrays, so I can only conclude that the above is, in fact, UB.
Am I correct?
What about the case of data
being declared as std::array<std::array<int, 2>, 2>
? This case seems even more likely to be UB, as structs may have padding.
Upvotes: 9
Views: 315
Reputation: 62603
Yes, you are correct, and there is not much to add to it. There are no mutidimensional arrays in C++ type system, there are only arrays (of arrays of arrays of arrays ad libitum).
Accessing an element beyond array size is undefined behavior.
Upvotes: 8