4.4. Multidimensioned Arrays

It can be helpful to keep this fact in mind when using what appears to be a multidimensioned array.An array whose elements are an array is said to have two dimensions. Each dimension is referred to by its own subscript:
// array of size 3, each element is an array of ints of size 4
int ia[3][4];
The first dimension is often referred to as the row and the second as the column. In C++ there is no limit on how many subscripts are used. That is, we could have an array whose elements are arrays of elements that are arrays, and so on.
ia[2][3] // fetches last element from the array in the last row
Initializing the Elements of a Multidimensioned Array
As with any array, we can initialize the elements by providing a bracketed list of initializers. Multidimensioned arrays may be initialized by specifying bracketed values for each row:
The nested braces, which indicate the intended row, are optional. The following initialization is equivalent, although considerably less clear.
int ia[3][4] = { /* 3 elements, each element is an array of size 4 */
{0, 1, 2, 3} , /* initializers for row indexed by 0 */
{4, 5, 6, 7} , /* initializers for row indexed by 1 */
{8, 9, 10, 11} /* initializers for row indexed by 2 */
};
As is the case for single-dimension arrays, elements may be left out of the initializer list. We could initialize only the first element of each row as follows:
// equivalent initialization without the optional nested braces for each row
int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
The values of the remaining elements depend on the element type and follow the rules descibed on page 112.If the nested braces were omitted, the results would be very different:
// explicitly initialize only element 0 in each row
int ia[3][4] = {{ 0 } , { 4 } , { 8 } };
initializes the elements of the first row. The remaining elements are initialized to 0.
// explicitly initialize row 0
int ia[3][4] = {0, 3, 6, 9};
Subscripting a Multidimensioned Array
Indexing a multidimensioned array requires a subscript for each dimension. As an example, the following pair of nested for loops initializes a two-dimensioned array:
When we want to access a particular element of the array, we must supply both a row and column index. The row index specifies which of the inner arrays we intend to access. The column index selects an element from that inner array. Remembering this fact can help in calculating proper subscript values and in understanding how multidimensioned arrays are initialized.If an expression provides only a single index, then the result is the inner-array element at that row index. Thus, ia[2] fetches the array that is the last row in ia. It does not fetch any element from that array; it fetches the array itself.
const size_t rowSize = 3;
const size_t colSize = 4;
int ia [rowSize][colSize]; // 12 uninitialized elements
// for each row
for (size_t i = 0; i != rowSize; ++i)
// for each column within the row
for (size_t j = 0; j != colSize; ++j)
// initialize to its positional index
ia[i][j] = i * colSize + j;
4.4.1. Pointers and Multidimensioned Arrays
As with any array, when we use the name of a multidimensioned array, it is automatically converted to a pointer to the first element in the array.

We define a pointer to an array similarly to how we would define the array itself: We start by declaring the element type followed by a name and a dimension. The trick is that the name is a pointer, so we must prepend * to the name. We can read the definition of ip from the inside out as saying that *ip has type int[4] that is, ip is a pointer to an int array of four elements.
int ia[3][4]; // array of size 3, each element is an array of ints of size 4
int (*ip)[4] = ia; // ip points to an array of 4 ints
ip = &ia[2]; // ia[2] is an array of 4 ints

int *ip[4]; // array of pointers to int
int (*ip)[4]; // pointer to an array of 4 ints
Typedefs Simplify Pointers to Multidimensioned Arrays
Typedefs (Section 2.6, p. 61) can help make pointers to elements in multidimensioned arrays easier to write, read, and understand. We might write a typedef for the element type of ia as
We might use this typedef to print the elements of ia:
typedef int int_array[4];
int_array *ip = ia;
The outer for loop starts by initializing p to point to the first array in ia. That loop continues until we've processed all three rows in ia. The increment, ++p, has the effect of moving p to point to the next row (e.g., the next element) in ia.The inner for loop actually fetches the int values stored in the inner arrays. It starts by making q point to the first element in the array to which p points. When we dereference p, we get an array of four ints. As usual, when we use an array, it is converted automatically to a pointer to its first element. In this case, that first element is an int, and we point q at that int. The inner for loop runs until we've processed every element in the inner array. To obtain a pointer just off the end of the inner array, we again dereference p to get a pointer to the first element in that array. We then add 4 to that pointer to process the four elements in each inner array.
for (int_array *p = ia; p != ia + 3; ++p)
for (int *q = *p; q != *p + 4; ++q)
cout << *q << endl;
Exercises Section 4.4.1
Exercise 4.36:Rewrite the program to print the contents of the array ia without using a typedef for the type of the pointer in the outer loop.