0

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.

Edenia
  • 2,312
  • 1
  • 16
  • 33
  • Not sure what your issue with warnings is. You seem to be suggesting that you can't get your compiler to warn in the second code snippet but clang certainly does: *suggest braces around initialization of subobject [-Wmissing-braces]* (three times). – Adrian Mole Mar 25 '23 at 06:45
  • What are you asking ? You said your way works so what is the problem ? – John3136 Mar 25 '23 at 06:46
  • I am wasting everyone's time. No I am just making a static analyzer. It's a bit more than that, but let's just say it's that :) – Edenia Mar 25 '23 at 06:47
  • You are right that GCC issues a warning with either `-Wall` or `-Wextra` though, my question still remains. – Edenia Mar 25 '23 at 06:49
  • 1
    @Fe2O3 What do you mean "try showing the rows and columns"? Showing to what? Why? I can show it to myself without curly braces too: `int arr[3][5] = {1,2,3, 4,5,6};` – Edenia Mar 25 '23 at 06:49
  • @Fe2O3 Really? Different how? – Edenia Mar 25 '23 at 06:52
  • @Fe2O3 I did. They are the same. Maybe you do that? – Edenia Mar 25 '23 at 06:55
  • 1
    It seems you're simply wasting time... Forget I was here. – Fe2O3 Mar 25 '23 at 06:57
  • There. I forgot. – Edenia Mar 25 '23 at 07:01
  • *For those who don't know - That person Fe2O3 deleted all his messages after realizing he was wrong and only left his last. – Edenia Mar 25 '23 at 20:04
  • For those who didn't see "those messages", the OP stated that their `int arr[3][5] = {1,2,3, 4,5,6};` was the same as `int arr[3][5] = { {1}, {2,3}, {4,5,6} };`. The OP suggests that using two SP's, instead of one, should delimit initialisation values in the same way as curly braces, but declines to test the difference... What can one do? (PS: 13 hours later, it seems Edenia didn't actually forget. Maybe s/he learned something...) – Fe2O3 Mar 26 '23 at 02:13
  • Hahaha, that was NOT what I claimed and I have screenshots. First of all I did test twice, second you claimed that the array will be initialized differently and the values will be different and since I did not observe this behavior I asked you to test it as well. Stop lying and covering it up and man up. – Edenia Mar 26 '23 at 07:47
  • PM: It was once easy to forget you were here since you haven't said anything remotely meaningful, but when you deleted your messages (which is not the right thing to do if you were convinced in your rightness) and started lying, now I have a very very good reason to never forget you. – Edenia Mar 26 '23 at 07:52

2 Answers2

2

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.

nielsen
  • 5,641
  • 10
  • 27
1

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.

Joël Hecht
  • 1,766
  • 1
  • 17
  • 18