OONSTD: Element Ordering 2D Arrays

E. Robert Tisdale (edwin@maxwell.hrl.hac.com)
Wed, 8 Jul 1998 16:27:45 -0700 (PDT)

The ordering of elements in a multi-dimensional array
has always been a source of confusion for programmers.
You may have heard that Fortran stores two-dimensional arrays
in column major order and C stores them in row major order.
But, in fact, Fortran and C compilers almost always store
multi-dimensional arrays in exactly the same way --
one element immediately after the other in a one-dimensional array.
The only difference between Fortran and C
is the order of the indices in the respective subscripting operators:

A(i, j) ! Fortran
A[i][j] /* C */

In Fortran, the leftmost index, i, changes faster than the rightmost index, j,
as you increment through the one-dimensional array
but exactly the opposite is true in C. The problem is that programmers
tend to think of two-dimensional arrays as matrices and always associate
the left index with a row and the right index with a column.
They get confused when they need to call a Fortran subroutine from C
or a C function from Fortran. The solution to this problem is simply
to remember that a two-dimensional array declared

real A(m, n)

in Fortran is equivalent* to a two-dimensional array declared

float A[n][m];

in C -- they simply appear to be transposes of each other.

Library developers eliminate this problem simply be providing
both a Fortran and a C language binding to their library.
If you use the Fortran binding, two-dimensional arrays appear to be stored
in column major order or in row major order if you use the C binding.

I believe that a C++ Matrix class should define
a subscripting operator [] which is consistent with C.
The argument should be a zero based index
and it should return a reference to a row of the matrix.
Another operator or a member function might be defined to accept
one based indices and to return a reference to a particular element.
It is not necessary to distinguish between row major order
and column major order if there is a stride associated with BOTH indices.
You simply swap strides and lengths to transpose the matrix.

Bob Tisdale

* The ANSI C Standard does not guarantee that A[i][n] == A[i+1][0].
The first element of a row might not follow immediately after
the last element of the previous row in memory but it is, in fact,
almost always true.