Search code examples
carray-initializationdesignated-initializer

gcc compiler report warning but a.out works smoothly otherwise


I am following the book "C Primer Plus" and encounter such a snippet of code:

// designate.c -- use designated initializers
#include <stdio.h>
#define MONTHS 12
int main(void) 
{
    int days[MONTHS] = {31, 28, [4] = 31, 30, 31, [1] = 29};
    int i;

    for (i = 0; i < MONTHS; i++)
        printf("%2d %d\n", i+1, days[i]);

    return 0;
}

It reports errors when I compiled it:

$ cc designate.c
designate.c:6:57: warning: initializer overrides prior initialization of this subobject [-Winitializer-overrides]
    int days[MONTHS] = {31, 28, [4] = 31, 30, 31, [1] = 29};
                                                        ^~
designate.c:6:29: note: previous initialization is here
    int days[MONTHS] = {31, 28, [4] = 31, 30, 31, [1] = 29};
                            ^~
1 warning generated.

Nonetheless, ./a.out works properly.

$ ./a.out
 1 31
 2 29
 3 0
 4 0
 5 31
 6 30
 7 31
 8 0
 9 0
10 0
11 0
12 0

I am very confused here about what should I learn from the error report?


Solution

  • While it is true that the warnings are often about serious issues, this one just says that something that you do doesn't make much sense and could be an oversight. Specifically

    int days[MONTHS] = {31, 28, [4] = 31, 30, 31, [1] = 29};
    

    Here you're having 28 for element 1, and then you're overwriting it to 29 with [1] = 29. So that 28 is gone, and that's what it warns you about. It translates to this:

    int days[MONTHS] = {31, 29, 0, 0, 31, 30, 31};
    

    And as you can see from your results:

    1 31
    2 29
    3 0
    4 0
    5 31
    6 30
    

    The 28 indeed is gone. The compiler doesn't know how important that 28 was to you, perhaps it was very important and [1] = 29 was a typo. That's why it warns you. And as you can also see, there's some whackiness with March and April having 0 days going on, surely this isn't what you intended.