user2635911
user2635911

Reputation: 492

Multidimensional array initialization in C

I am reading the book, "Programming in C" by Kochen and I am confused where he explains the initialization of multidimensional array

here

In particular, I don't understand the meaning of the following sentence Note that, in this case, the inner pairs of braces are required to force the correct initialization. Without them, the first two rows and the first two elements of the 3rd row would have been initialized instead. I'm not sure what the heck the sentence means.

Upvotes: 14

Views: 58910

Answers (5)

Daniel K
Daniel K

Reputation: 158

With the inner braces the array looks like this:

10  5 -3  0  0
 9  0  0  0  0
32 20  1  0  0
 0  0  8  0  0

So in every line the last 2 values are zero (because you didn't set a value for them. Without the inner braces the array would look like this:

10  5 -3  9  0
 0 32 20  1  0
 0  8  0  0  0
 0  0  0  0  0

Only the first 12 elements would become the given values and the rest will be 0.

Upvotes: 9

Joseph Myers
Joseph Myers

Reputation: 6552

This is because the M[4][5] array has 20 elements (4 rows, 5 columns), and the default order for initialization is row-by-row if rows are not explicitly specified by using inner pairs of braces.

What this means is that if you assign the same 12 values as a simple linear list, without the inner pairs of braces, then values are assigned to the first two rows (2*5 = 10 elements) plus the first 2 columns of the third row. (The remaining 8 elements of the array which you did not explicitly initialize will automatically be set to 0.)

The C compiler is aware that each row only has 5 columns, and will automatically wrap the list of numbers onto the next row each time the 5-column margin is reached. Thus,

int M[4][5] = {10, 5, -3, 9, 0, 0, 32, 20, 1, 0, 0, 8};

is understood to mean

int M[4][5] =
{
  {10,  5, -3, 9, 0},
  { 0, 32, 20, 1, 0},
  { 0,  8,  0, 0, 0},
  { 0,  0,  0, 0, 0}
};

You can override the default order by using inner braces to separate your 12 values into rows of your own liking (but naturally not more than 5 columns per row for this definition of an array M).

For instance, when you use inner braces to separate the same 12 values into four sets of 3 like your page from the book shows, then those inner braces are interpreted to initialize separate rows of the multidimensional array. And the result will be initializing four rows of the array, but only the first 3 columns of those four rows, setting the remaining columns to zero (two blank zero values at the end of each row).

That is to say, the C compiler is aware that the array M has 5 columns in each row, and so it will add the missing columns to each row so that each row has 5 columns, and so the array will have a total of 20 values:

int M[4][5] =
{
  {10,  5, -3},
  { 9,  0,  0},
  {32, 20,  1},
  { 0,  0,  8}
};

is understood to mean

int M[4][5] =
{
  {10,  5, -3, 0, 0},
  { 9,  0,  0, 0, 0},
  {32, 20,  1, 0, 0},
  { 0,  0,  8, 0, 0}
};

Upvotes: 17

Keith Thompson
Keith Thompson

Reputation: 263177

It would help to see the specific example.

A multidimensional array is an array of arrays. (It's not just syntactic sugar for a long 1-dimensional array.)

In an initializer, it's legal to omit both trailing elements (which are implicitly initialized to zero) and inner curly braces.

Given:

int arr[2][2];

a full initialization might look like:

int arr[2][2] = { { 10, 20 }, { 30, 40 } };

You can (but IMHO shouldn't) omit the inner braces:

int arr[2][2] = { 10, 20, 30, 40 };

and the compiler will map the elements of the initializer to the elements of arr.

If you omit trailing elements:

int arr[2][2] = { { 10, 20 } };

then the second row is implicitly initialized to { 0, 0 }.

Or you could write:

int arr[2][2] = { { 10 }, { 20 } };

which would assign the values 10 and 20 to the first element of each row, not to the first row.

Again, it's hard to tell exactly what the author was talking about without seeing an example, but an inner brace tells the compiler to start a new row, even if the first row is incomplete.

If you supply initializers for all 4 elements (or more generally all X * Y elements), the inner braces are not strictly necessary; the order of the elements is the same either way.

Personally, I find it much clearer to include all the inner braces anyway, because they reflect the actual structure you're initializing.

(So what's the difference between a 1-dimensional array and a 2-dimensional array, apart from syntactic sugar? Given the above declaration of arr, if it were the same as a 1-dimensional array then arr[0][2] would be the same as arr[1][0], with the second index overflowing into the second row. And it may work that way in practice, but actually arr[0][2] has undefined behavior. This does have practical consequences; an optimizing compiler may assume that all bounds are within range, and generate code that misbehaves if that assumption is violated.)

See also this question.

Upvotes: 2

Alexandru Barbarosie
Alexandru Barbarosie

Reputation: 2992

Since all arrays internally behave as 1d arrays you have to specify with the brackets which rows exactly you initialize.

For exemple:

int a[4][5] = {
              { 1, 2, 3 },  // those are the elements of the first row.
                            // only the first 3 elements are initialized
              { 1, 2, 3, 4} // those are the elements of the 2nd row.
                            // only the first 4 element are initialized
              };
                            // everything else will be equal to 0

while

int a[4][5] = { 1, 2, 3, 1, 2, 3, 4}; // this will initialize first 5 elements 
                                      // of the first row and then continue 
                                      // with the 2nd one making the first 2 
                                      // elements to be 3 and 4 respectivly
                                      // everything else will be equal to 0

Upvotes: 8

1''
1''

Reputation: 27095

Multidimensional arrays in C are just "syntactic sugar" for one-dimensional arrays. When you allocate a 4 x 5 int array, you're really allocating space for 20 integers in a row in memory. These integers are stored as all the elements of the first row, then all the elements of the second row, etc.

Without the inner braces, your initializer is 1D as well, and indicates that you want to initialize the first 12 of these 20 integers, namely the first two rows and the first two elements of the third row.

Upvotes: 3

Related Questions