← All Lessons Lesson 16 / 68
Lesson 16

Column-Major Order with a 3D Array: How the Computer Finds Each Element

Storing a 3D Array in Memory (Column-Major Order)

A computer's memory is really just one long line of numbered boxes, one after another. But sometimes we want to store data that has more than one direction — like a 3D array, which you can picture as a stack of small tables. The computer has to take that 3D shape and flatten it into a single straight line. The rule it uses to decide *what order* to lay the elements down is called the ordering. Here we use column-major order.

Our example array

Let us use a three-dimensional integer array:

int array[2][2][3]

This holds 2 × 2 × 3 = 12 numbers. We will call them value1 through value12. The three sizes are named D3 = 2, D2 = 2, and D1 = 3. Think of it as 2 small tables, each table having 2 rows and 3 columns.

The flattening rule: leftmost index moves fastest

In column-major order, the leftmost index changes the quickest, and the rightmost index changes the slowest. So the computer counts up the first index first, then steps the second, then the third — exactly like a car's odometer where the right-most wheel of digits spins fastest, but here it is flipped to the left.

Here is the exact order the 12 elements are placed in memory:

  1. array[0][0][0]
  2. array[1][0][0]
  3. array[0][1][0]
  4. array[1][1][0]
  5. array[0][0][1]
  6. array[1][0][1]
  7. array[0][1][1]
  8. array[1][1][1]
  9. array[0][0][2]
  10. array[1][0][2]
  11. array[0][1][2]
  12. array[1][1][2]

Notice how the first [ ] flips between 0 and 1 on every single step, the second [ ] changes more slowly, and the third [ ] only moves after a whole group is finished. That is what "highest dimension moves fastest" means.

Where exactly does each element sit?

To place these in memory we need two more facts:

  • Base address = 2 (the memory box where the array starts).
  • Size of each element = 4 bytes (because integers take 4 bytes each).

So element 1 sits at byte 2, element 2 at byte 2 + 4 = 6, element 3 at byte 10, and so on — each new element is 4 bytes further along.

The address formula

When you write array[i][j][k], the language does not search for the element. It calculates its address instantly using a formula. The program already knows the dimensions, the base address, and the element size — that is all it needs.

For our column-major array the formula is:

address[i][j][k] = base + size * ( i + D3 * ( j + D2 * k ) )

With base = 2, size = 4, D3 = 2, D2 = 2.

Example 1 — array[0][0][1]:

= 2 + 4 * ( 0 + 2 * ( 0 + 2 * 1 ) )
= 2 + 4 * ( 0 + 2 * 2 )
= 2 + 4 * 4
= 18

Example 2 — array[1][1][2]:

= 2 + 4 * ( 1 + 2 * ( 1 + 2 * 2 ) )
= 2 + 4 * ( 1 + 2 * 5 )
= 2 + 4 * 11
= 46

So the element at array[0][0][1] begins at byte 18, and the element at array[1][1][2] begins at byte 46. No scanning, no loops — just one quick piece of arithmetic.

The last step: dereferencing

Knowing the address only tells the computer *where* the data starts. The final step is dereferencing: reading the actual value out of memory. Because the language knows the type is int (4 bytes), it reads the 4 bytes starting at that address and turns them into a whole number. If it were a different type, it would simply read a different number of bytes.

The big takeaway

All of this — the flattening, the address formula, the dereferencing — happens silently under the hood in almost every modern programming language. As a programmer you just write array[i][j][k], and the language quietly does the math to find and read the right bytes. We used 4-byte integers here, but the exact same idea works for any datatype; only the element size changes.

Column-Major Order with a 3D Array: How the Computer Finds Each Element
Diagram — click to zoom (scroll / drag to pan)