Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Omitting Sizes while Initializing C/C++ Multidimensional Arrays

What I know about C/C++ compilers is that they ignore inner braces while initializing multidimensional arrays.

So, you can't do this:

int myArray[][] = { { 2, 3 }, { 4, 5 }, { 4, 1 } }; 

because the compiler will see it exactly as

int myArray[][] = { 2, 3, 4, 5, 4, 1 }; 

and now it doesn't know if it is 6 * 1, 3 * 2, 2 * 3, 1 * 6, or even something else (since this can be a partial initialization list, not necessarily complete).

My question is, why does this work in many compilers?

int myArray[][2] = { { 2 }, { 4, 5 }, { 4, 1 } }; 

The compiler "intuitively" sees it as:

int myArray[][2] = { { 2, 0 }, { 4, 5 }, { 4, 1 } }; 

which means it doesn't ignore the braces. I've tried it on three different compilers till now and all worked.

I expect the answer to be "this is just compiler-dependent". I don't have access to the standard, so please provide an answer from the standard. I don't need gut feelings, I have mine.

like image 840
OmarOthman Avatar asked Mar 12 '14 08:03

OmarOthman


People also ask

Which dimensions can we omit when declaring a multidimensional array?

The accepted answer to this question explains it pretty well. Think of an n-dimensional array as a simple array with n-1 dimensional elements. Just as you don't pass the size of a 1 dimensional array, you don't pass the size of the first dimension of an n dimensional array.

Can we initialize 2D array without size?

You can create a two-dimensional array without specifying both dimensions like int[4][] is a valid array declaration. It also allows you to create a multi-dimensional array whose rows can vary in length, as we have seen in our second example.

Which is the correct way to declare a multidimensional array in C?

The basic form of declaring a two-dimensional array of size x, y: Syntax: data_type array_name[x][y];


1 Answers

The following is from section A8.7 of "The C Programming Language" by K&R, 2nd edition, pages 219,220:

An aggregate is a structure or array. If an aggregate contains members of aggregate type, the initialization rules apply recursively. Braces may be elided in the initialization as follows: if the initializer for an aggregate's member that is itself an aggregate begins with a left brace, then the succeeding comma-separated list of initializers initialize the members of the sub aggregate; it is erroneous for there to be more initializers than members. If, however, the initializer for a subaggregate does not begin with a left brace, then only enough elements from the list are taken to account of the members of the subaggregate; any remaining members are left to initialize the next member of the aggregate of which the subaggregate is a part. For example,

 int x[] = { 1, 3, 5 };  

declares and initializes x as a 1-dimensional array with three members, since no size was specified and

there are three initializers.

Therefore, given this line

int myArray[][2] = { { 2 }, { 4, 5 }, { 4, 1 } }; 

the compiler will recursively initialize the array, noting that each subarray starts with a left brace and has no more than the required number of initializers, and will count the number of subarrays to determine the first dimension of the array.

The following is from section A8.7 of "The C Programming Language" by K&R, 2nd edition, page 220:

float y[4][3] = {     { 1, 3, 5 },         { 2, 4, 6 },     { 3, 5, 7 } }; 

is a completely-bracketed initialization: 1,3 and 5 initialize the first row of the array y[0], namely y[0][0], y[0][1], and y[0][2]. Likewise the next two lines initialize y[1] and y[2]. The initializer ends early, and therefore the elements of y[3] are initialized with 0. Precisely the same effect could have been achieved by

float y[4][3] = {    1, 3, 5, 2, 4, 6, 3, 5, 7  }; 

Note that in both cases, the fourth row of the array will be initialized with zero, since not enough initializers were specified.

float y[4][3] = {      { 1 }, { 2 }, { 3 }, { 4 }  }; 

initializes the first column of y and leaves the rest 0.

So the compiler doesn't ignore the inner braces. However, the inner braces are optional if you specify all of the initializers in order with no gaps. Using the inner braces gives you more control over the initialization, if you don't want to specify a full set of initializers.

like image 130
user3386109 Avatar answered Sep 21 '22 12:09

user3386109