Why linearization is needed
Memory is one-dimensional, but arrays are not. To store a 2-D matrix with rows and columns, the compiler must pick an order in which to flatten the cells into consecutive addresses. There are two standard choices.
- Row-major (C, C++, Python/NumPy default, Pascal): rows are laid down one after another — The last index varies fastest.
- Column-major (Fortran, MATLAB, R, Julia): columns are laid down one after another — The first index varies fastest.
Address formulas
Let be the base address, the size of one element (in bytes), and assume 0-based indices.
The quantity multiplied by is the linear index. With 1-based indices and lower bounds , replace and .
How to read a problem
The diagnostic trick: pick two cells, see which index changed, and measure the address gap (the stride).
| Move (other index fixed) | Row-major stride | Column-major stride |
|---|---|---|
| change column index by 1 | (one element) | (a whole column) |
| change row index by 1 | (a whole row) | (one element) |
So: a big jump when the row index moves row-major; a big jump when the column index moves column-major.
Mini-example
Suppose and . Only the row index changed (), and the address advanced by bytes. Jumping a full row width when the first index increments is the row-major signature, so the matrix is stored row-major. (Had the same 16-byte jump come from changing the column index, it would have been column-major.)
Generalizing to dimensions
For dimensions , row-major weights each index by the product of all later dimension sizes:
Column-major instead weights each index by the product of all earlier dimension sizes.
Exam trick: Always ask which index moved and how big the gap is before deciding. A small one-element stride means that index varies fastest (last index in row-major, first in column-major); a large stride means you crossed a whole row or column. Also watch for 1-based indexing and a nonzero base — subtract the lower bound before plugging into the formula.