Never allow a programmer like this to park your car. The storage and a reference to an individual
element are actually laid out in linear memory as shown in Figure 10-2.
Figure 10-2. Actual Memory Layout of a Two-dimensional Array
The rules for array subscripting (see Chapter 9, page 242) tell us that to evaluate the l-value pea[i][j],
we take whatever is at pea[i] and then get the character at offset [j] from there. Thus, pea[i][j]
is resolved by the compiler as
((pea+i)+j)
But (and here's the key point!) the meaning of "pea[i]" varies depending on how pea was defined.
We'll come back to this expression in a minute, but first let's take a look at a very common and
important C data structure: the one-dimensional array of pointers to strings.
An Array of Pointers Is an "Iliffe Vector"
A similar effect to a two-dimensional array of char can be obtained by declaring a onedimensional
array of pointers, each of which points to a character string. [1] The C declaration for this is
[1] We're simplifying things very slightly here—the pointer is actually declared as a pointer to a
single character. By declaring a pointer-to-character we leave open the possibility that other
characters can be stored adjacent to the first, implicitly forming a string. A declaration like
char (* rhubarb[4])[7]; is truly the way we declare an array of pointers to strings. This
is never seen in practice, as it constrains the size of the pointed-to arrays unnecessarily (to be
exactly seven characters long).
char * pea[4];
Software Dogma
Reminder on Declaration Syntax
Note that char *turnip[23] declares "turnip" to be a 23-element array, each element of
which is a pointer to a character (or a character-string—there's no way to distinguish from