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 objectxwithnelements, the expressions P + J and J + P (where J has the valuej) point to the (possibly-hypothetical) elementx[i+j]if 0 ≤i + j≤nand 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.