5.1.11 · D1C Programming

Foundations — Multi-dimensional arrays

1,994 words9 min readBack to topic

This page assumes nothing. Before you can trust the parent note Multi-dimensional arrays, you need a handful of small ideas — memory boxes, addresses, sizeof, what a pointer is, what a "type" means, and what the square brackets [] secretly do. We build each from a picture, then show how they stack into the topic.


0. The absolute floor: memory is a numbered street of boxes

Forget arrays. A computer's memory is a long row of tiny boxes, each holding exactly one byte (a byte = a small number, 0–255). Every box has a house number called its address.

Figure — Multi-dimensional arrays

Why the topic needs this. The whole parent note is about where a[i][j] lives on this street. If "address" and "base" are fuzzy, the formula is meaningless. Every symbol in that formula is a position on this street.


1. sizeof — how many boxes one value eats

One byte is tiny. Real values need several boxes side by side. An int (a whole number) typically takes 4 boxes; a char takes 1; a double takes 8. This box-count is what the sizeof operator reports.

sizeof(char)   // 1
sizeof(int)    // 4  (on most machines)
sizeof(double) // 8

Why the topic needs it. The address formula counts elements first, then multiplies by to convert to bytes. Without you could count "9 elements past the start" but never turn that into a real house-number. is the elements→bytes exchange rate.


2. Type — the label that tells you the box-count AND the meaning

A type is a promise about a value: how many boxes it uses and how to read those boxes.

Why the topic needs it. The parent says "Type of a is array of 3 arrays of 4 ints". That sentence is doing real work: the type is exactly what tells the compiler how far one a+1 jump moves. Types are the source of all the jump distances.


3. [] on a 1-D array — the square brackets are a counting instruction

Now the first array. Declaring

int x[5];   // five ints in a row

reserves 5 fences of 4 boxes = 20 boxes, all touching. See C Arrays (1D).

Figure — Multi-dimensional arrays

Why the topic needs it. int a[3][4] is secretly "an array of 3 things". So a[i] uses this exact rule — except each "element" of a is itself a whole row of 4 ints, so one jump is bigger. Understanding one-index jumps first makes two-index jumps obvious.


4. Pointer — a value that is an address

A pointer is a variable whose stored value is an address (a house-number pointing at another box). See Pointers in C.

Figure — Multi-dimensional arrays

Why the topic needs it. The parent's key claim is a[i][j] ≡ *(*(a+i)+j). Every piece of that — the *, the +i, the "jump a whole row" — is exactly pointer arithmetic from this section. And crucially: a+i jumps a row because a has type int(*)[4], a pointer whose element is a 4-int row, so its jump is bytes.


5. and · and superscripts — the tiny math notations

Three symbols the parent uses without warning:

Why the topic needs it. In addr = base + (i·C + j)·s, the parentheses and dots are the difference between a correct address and garbage. And is what licenses swapping a[i][j] for *(*(a+i)+j) at will.


6. Row-major — the choice of how to flatten a grid

A grid has no built-in "reading order". C picks one: row-major — finish an entire row before starting the next. (Fortran/MATLAB pick the other; see Row-major vs Column-major.)

Figure — Multi-dimensional arrays

Why the topic needs it. This choice is why the count is and not something else. Change the flattening rule and the whole address formula changes.


7. Array decay — why a grid quietly becomes a pointer

When you use an array's name in most expressions (or pass it to a function), the name decays into a pointer to its first element. See Array Decay and, for the subtle int (*p)[4] vs int *p[4] split, Pointer to Array vs Array of Pointers.

Why the topic needs it. Decay is the bridge between the declared grid and the pointer formula. It explains the parent's rule "you must pass every dimension except the first": once decayed, only the column count survives in the pointer's type, and is the one thing the address math needs.


The prerequisite map

Memory as numbered boxes

Address and base

sizeof gives s

Type fixes box-count and meaning

1D array x k = base + k times s

Pointer holds an address

p plus 1 jumps one element

Array name decays to pointer

Row-major flattening

addr = base + i C + j times s

Multi-dimensional arrays


Equipment checklist

What is an address in memory?
The house-number (an integer) of a specific one-byte box on the numbered "street" of memory.
What does sizeof(T), our symbol , tell you?
How many bytes (boxes) one value of type T occupies — the exchange rate between "element count" and "byte count".
Why does a type matter beyond box-count?
It also decides how those boxes are decoded (int vs float read the same 4 boxes differently) and fixes the pointer jump size.
Write the 1-D address rule for x[k].
.
What is a pointer and what does *p do?
A pointer holds an address; *p (dereference) goes to that address and reads the value there.
If p has type int*, how many bytes does p + 1 advance?
sizeof(int) bytes (4 on most machines) — one whole element, not one byte.
What does mean when we write a[i][j] ≡ *(*(a+i)+j)?
"Is exactly / by definition the same thing" — the two forms are identical, not merely similar.
Define row-major order in one sentence.
Store an entire row before the next, so the leftmost (row) index changes slowest and the rightmost (column) index fastest.
When int a[3][4] decays, what pointer type do you get and why does a+1 jump 16 bytes?
It decays to int(*)[4] (pointer to a 4-int row); adding 1 advances one whole row = bytes.
Why does the address formula use the column count but never the row count ?
To locate a[i][j] you skip full rows of elements then more — the arithmetic contains but has no place for .

Connections

  • Multi-dimensional arrays — the parent this page prepares you for.
  • C Arrays (1D) — the single-index rule these all build on.
  • Pointers in C — addresses stored as values; dereferencing.
  • Array Decay — how a grid name becomes a pointer.
  • Pointer to Array vs Array of Pointers — the int(*)[4] vs int*[4] distinction.
  • sizeof Operator — the source of .
  • Row-major vs Column-major — the flattening choice C makes.
  • Variable Length Arrays (C99) — where the "pass the column" rule reappears.