If you have a one-dimensional array like
int a[] = {1, 2, 3};
it looks like this in memory:
+---+---+---+
a: | 1 | 2 | 3 |
+---+---+---+
And if you then have a pointer to the array's first element:
int *ip = &a[0];
you get something that, by the rules of pointer arithmetic in C, works just about exactly like the array:
+---+---+---+
a: | 1 | 2 | 3 |
+---+---+---+
^
|
+-|-+
ip: | * |
+---+
But a two-dimensional array looks like this:
int a2[2][3] = { { 1, 2, 3 } , { 4, 5, 6 } };
+---+---+---+---+---+---+
a2: | 1 | 2 | 3 | 4 | 5 | 6 |
+---+---+---+---+---+---+
Or we could draw it like this:
+---+---+---+
a2: | 1 | 2 | 3 |
+---+---+---+
| 4 | 5 | 6 |
+---+---+---+
But the problem is that this layout is not compatible with a pointer-to-pointer. If we have
int **p2;
and if we initialize it to point to some pointers that point to some integers, it'll end up looking more like this:
+---+
p2: | * |
+-|-+
|
v
+---+ +---+---+---+
| *--------> | | | |
+---+ +---+---+---+
| *-----.
+---+ \ +---+---+---+
`----> | | | |
+---+---+---+
And the problem is that there's nothing in a2
for our pointer p2
to point at that'll work. Since p2
is a pointer-to-a-pointer, it needs to point to a pointer in order to work. But there's no pointer anywhere in a2
's representation that can fill this role.