Why are 2-D arrays reversed?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Thu Oct 11 03:32:02 UTC 2018


On Wednesday, October 10, 2018 4:26:40 PM MDT Chris Katko via Digitalmars-d-
learn wrote:
> On Wednesday, 10 October 2018 at 16:00:42 UTC, Steven
>
> Schveighoffer wrote:
> > On 10/10/18 9:22 AM, Chris Katko wrote:
> >> int[][] data =
> >>
> >>      [
> >>          [1, 0, 1, 0, 0],
> >>          [1, 0, 1, 0, 0],
> >>          [1, 0, 1, 1, 1],
> >>          [1, 0, 0, 1, 0],
> >>          [5, 1, 1, 1, 0]
> >>      ];
> >>
> >> when drawn with data[i][j], prints the transpose of "data":
> >>
> >> [1, 1, 1, 1, 5]
> >> [0, 0, 0, 0, 1]
> >> [1, 1, 1, 0, 1]
> >> [0, 0, 1, 1, 1]
> >> [0, 0, 1, 0, 0]
> >>
> >> So, if I flip [i][j] and print a row of "j's", it'll be
> >> correct. It's very confusing and counter-intuitive to have to
> >> remember to swap i and j every time I use an array.
> >>
> >> I guess when I load data from files, the i/j are already
> >> swapped and stay consistent, but when using an array in source
> >> code, they have to be flipped.
> >
> > I'm not sure what code you are using, but it prints out just
> > fine for me:
> >
> > https://run.dlang.io/is/hrA0tj
> >
> > -Steve
>
> Ah, here's a simple example:
>
> int[][] data3 =
>   [
>       [1, 0, 1, 0, 0],
>       [1, 0, 1, 0, 0],
>       [1, 0, 1, 1, 1],
>       [1, 0, 0, 1, 0],
>       [5, 1, 1, 1, 0]
>   ];
>
>   for(int i = 0; i < 5; i++)
>       {
>       for(int j = 0; j < 5; j++)
>           {
>           write(data4[i][j]," ");
>           }
>       writeln();
>       }
>
>    1 0 1 0 0
>    1 0 1 0 0
>    1 0 1 1 1
>    1 0 0 1 0
>    5 1 1 1 0
>
> I have to draw j's first. I have to iterate through the
> "y"/columns/j to get the the "x's" first.
>
> I mean, I guess it makes sense if the outer-most array indexer
> refers to the inner-most "element".
>
> Wait, this IS the same as C, isn't it? So maybe this is just a
> "new" problem for me since I rarely-if-ever use hardcoded
> arrays...
>
> Maybe my brain is just melting.

The situation is bascially the same as C, though trying to make the type
syntax more consistent by putting it all on the left-hand side of the
variable has made things more confusing. The types read basically the same
as in C. The primary difference is that in D, the static array sizes go with
the type and not the variable name, which means that they're on the
left-hand side rather than the right. So, you get

int[5][4] arr;

instead of

int arr[4][5];

In both cases, the type is read outward from the variable name (which is
basically how the compiler reads types in both C and D, though understanding
that is more critical in C because of C's function pointer syntax). It's
just that in the D case, this then seems backwards, because when you then
index the array, the left index has $ of 4 and the right has $ of 5, which
is the reverse of the order in the declaration, whereas in C, the order
matches, because the sizes went on the right-hand side. One sort of
consistency was traded for another. With dynamic arrays, the sizes are
always given on the right-hand side, so you don't get that reversal. So,
what D does is reasonably consistent and matches C in terms of how types are
read, but it does end up being annoyingly hard to wrap your head around,
because the result is that the sizes of multi-dimensional, static arrays are
then declared in the opposite order from the order that they're accessed in.
If it weren't for the fact that D does out-of-bounds checking for all array
accesses in @safe code or when -release is not used, it would likely to be a
huge problem with such arrays in practice. Fortunately, since the checks are
almost always in place, the inevitable mistakes are usually quickly caught.

- Jonathan M Davis





More information about the Digitalmars-d-learn mailing list