Flat-list initializer for an array in C

72 Views Asked by At

An exemplary 2D array initialization goes like this:

int arr[3][5] = { {0,1,2,3,4}, {5,6,7,8,9}, {10,11,12,13,14} };

We are taught that this is the "correct way" of initializing an array. But is it really "correct" as if it is incorrect to use a single flat-list compound literal? Turns out this is also compilable:

int arr[3][5] = { 0,1,2,3,4, 5,6,7,8,9, 10,11,12,13,14 };

(Which probably has to do with the fact that all array elements are laid out in contiguous memory.)

In terms of lexics, both codes compile and seemingly produce the same result in GCC. The former evidently wins in terms of readability, except in some cases it makes it worse. And I don't see why we can't just separate "dimensions" with spaces as I just did. I am particularly interested in exactly what this means to the compiler. I was not able to make it produce warnings that can only depend on the presence of curly braces. Excess elements can be detected either way. If the only problem is in the compiler's diagnostic, then I would like to know which warnings/errors fire up only when braces are present.

2

There are 2 best solutions below

0
nielsen On BEST ANSWER

You are free to use formatting to improve readability for humans, e.g.:

   int a[3][5] = {
       0,1,2,3,4,
       5,6,7,8,9,10,
       11,12,13,14,15
   };

However, it does not matter to the compiler which does not have any rules to treat special whitespace as e.g. a separator.

The compiler needs the braces to know your intent:

   int a[3][5] = {
       {0,1,2,3,4},
       {5,6,7,8,9,10},
       {11,12,13,14,15}
   };

Knowing this, the compiler is able to issue a warning if something seems off:

   int a[3][5] = {
       {0,1,2,3,4},
       {5,6,7,8,9,10,11},  // <--- excess elements in array initializer
       {12,13,14,15}
   };

or place initializer constants correctly:

   int a[3][5] = {
       {0,1,2,3,4},
       {5,6,7},    // Use default value for remaining elements
       {11,12,13,14,15}
   };

Btw., GCC (v 11.2.0 with -Wall -Wextra) does not issue any warning for empty braces:

   int a[3][5] = {
       {0,1,2,3,4},
       {},    // Use default value for entire row
       {11,12,13,14,15}
   };

The C language and modern compilers offer us a great deal of help, but even more freedom, including the freedom to write confusing and unmaintainable code. The "correct" way of doing things (whether defined by teaching or a company coding standard) are rules which we as users of the language pose on ourselves to make code understandable and robust. If you are coding for yourself, you have the freedom to define your own "correct" way of doing things.

0
Joël Hecht On

Curly braces allow the compiler to interpret the code more accurately, in order to detect human errors, or to allow shorter code.

For example:

static int arr[3][5] = { {0,1,2,3}, {5,6}, {10,11,12,13} };

Is correct, and allow the coder to write shorter code taking advantage of default values.

Other example:

static int arr[3][5] = { {0,1,2,3,4,5}, {6,7,8,9}, {10,11,12,13,14} };

The compiler will detect an error. Is it truly an error since there's still 15 int in memory? Yes IMO. C is a high level language, close to the machine yes, but it is not assembly: using multiple dimensions in a array is more than just a memory size allocation.

Compilers are not perfect either:

static int array_4[3][5] = { {0,1,2,3,4}, { }, {10,11,12,13,14} };

Here Visual C++ detects an error because of empty { }. But IMO this syntax should be acceptable.