P.JBoy
P.JBoy

Reputation: 105

Is accessing the middle of a multidimensional array via a pointer to its first element UB?

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 object x with n elements, the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) element x[i+j] if 0 ≤ i + jn and the expression P - J points to the (possibly-hypothetical) element x[i−j] if 0 ≤ i − jn.
    • 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

Answers (1)

SergeyA
SergeyA

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

Related Questions