Let\'s say we have a 2D int array:
int a[3][4] = { { 1,3,2,4 }, { 2,1,5,3 }, { 0,8,2,3 } };
Is it legal and valid to take its
A 2D array cannot be treated as a 1D array
As noted by @KillzoneKid, the address of an array is not pointer interconvertable with that of the first element even though they share the same address value.
constexpr provides a convenient way to evaluate UB. Compilers are required to detect UB when constexprs are evaluated. Thus a simple test can be made. This function, when evaluated during compile time will detect accessing values beyond an array's range.
// sum "n" sequential ints
constexpr int sum(const int* pi, int n) {
int sum = 0;
while (n-- > 0)
sum += *pi++;
return sum;
};
When this is called at runtime with a pointer to the first element of a 1D or 2D array it will sum the elements but is UB if "n" goes beyond the boundary of the array. For a 2D array, this would be the extent of the lowest dimension. Not the size of the whole array.
Examining different instances of a pointer to an int we can see UB occurs once we try to access a value beyond the array dimension.
int main()
{
constexpr int i0{1};
constexpr int i1[2]{ 1,2 };
constexpr int i2[2][2] = { { 1,2}, {3,4} };
constexpr int sum0 = sum(&i0, 1); // fails for n>1
constexpr int sum1 = sum(&i1[0], 2); // fails for n>2
constexpr int sum2 = sum(&i2[0][0], 2); // fails for n>2
const int sum3 = sum(&i2[0][0], 4); // runtime calc, UB. fails if constexpr
return sum0 + sum1 + sum2 + sum3; // 17
}
For accesses beyond existing data, such as in sum0 and sum1, UB is clear. But sum2 points to existing data for n=[0:3) yet constexpr evaluation shows it to be UB for n=4.
I was somewhat surprised to learn this. Every compiler I've ever used worked as expected when doing things like scaling all the coefficients of a matrix by a fixed amount. But I can see rationales based on optimization assumptions that portions of a matrix won't change from the result of a function call on another part not in the same array sequence.