Is it safe to sort a 2D array as shown in the code below?
My insight into corner cases isn't good, but this seems safe as long as your not accessing illegal indices.
The allotted 2D array locations are contiguous in memory, such for a[3][3]
:
a[0][0]..a[0][1]..a[0][2]..a[1][0]..a[1][1]..a[1][2]..a[2][0]..a[2][1]..a[2][2]
Since std::sort
uses the [first,last) range, applying it over that range from a[0][0]
to a[2][2]+1
makes sense, i.e.:
sort(&a[0][0], &a[2][2]+1);
or considering from the base address instead of the end location:
sort(&a[0][0], &a[0][0]+(3*3));
gives the correct answer, although at the first sight it may seem to be undefined behaviour as &array[0][0]+(dim1*dim2)
seems to be out of range. But it never accesses illegal indices, as the pointer (following pointer arithmetic) would only go from a[0][0]
to a[2][2]
, following increments of the size of an integer, for an int
2D array. Uptil this point it seems correct or safe.
However, what Jarod wants to convey holds true as well - that we have two arrays in context, and a[0][0]..a[2][2]
isn't the same as a[0]..a[9]
, as the type of the former would still pertain to int(*)[3]
, considering our array a[3][3]
passed to std::sort
.
Elaborating on what he said:
Passing from (&a[0][2]) + 1
is one past the end of array a[0]
. &a[1][0]
, which is at same location belongs to another array:
a[0][0]..a[0][1]..a[0][2] -> Array 1
// a[0][2] + 1 -> exceeds index of the first array among the three arrays of the array which forms a[3][3]
a[1][0]..a[1][1]..a[1][2] -> Array 2
a[2][0]..a[2][1]..a[2][2] -> Array 3
If it were to be still correct (if you assume) then it would only make sense if ((&a[0][2]) + 1) - &a[1][0]
would equal to 0. But its proven to show undefined behaviour and not 0, as demonstrated by Jarod in his demo here, with a corresponding example between (&a[0][0] + 3)
and &a[1][0]
. (Clang shows an error which can be used to justify the UB case)
And can we generalize this way for any multidimensional array?
Yes, why not?
Here's one for a three dimensional one:
#include <iostream>
#include <algorithm>
int main()
{
int a[2][2][2];
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++)
std::cin >> a[i][j][k];
std::sort(&a[0][0][0], &a[0][0][0] + 2 * 2 * 2);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++)
std::cout << a[i][j][k] << " ";
std::cout << "\n";
}
}
}