32

I have this struct in C below that I want to initialize to all zero. How do I get rid of the missing braces warning?

typedef struct {
    uint32_t incoming[FRAME_TYPE_MAX];
    uint32_t outgoing[FRAME_TYPE_MAX];
    uint32_t timeouts;
    uint32_t crc_errors;
} pkt_t;

static pkt_t stats = {0};
fred basset
  • 9,774
  • 28
  • 88
  • 138
  • 7
    Using `{0}` as an initializer is a very useful idiom. It's valid for *any* type, and it initializes all members to zero (0, 0.0, or NULL). It's unfortunate that gcc doesn't recognize this. – Keith Thompson Jul 19 '12 at 00:08

8 Answers8

39

This is GCC bug # 53119:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119

If you want to see it fixed, post a followup to the bug report indicating that it's a problem for you.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 2
    It seems that one can however reorder struct members so that the first one becomes a scalar, and the warning disappers. This is not an option when you need to reinterpret e.g. memory-mapped device registers, though in most cases this may be considered as a workaround. – Eldar Abusalimov Oct 15 '13 at 15:37
  • 1
    That may or may not be possible, but it's definitely not an appropriate solution. – R.. GitHub STOP HELPING ICE Oct 16 '13 at 03:28
  • 1
    It's not a solution. It is a _temporal workaround_ until GCC bug is fixed. – Eldar Abusalimov Oct 16 '13 at 08:08
  • 2
    And the GCC bug has reportedly been fixed. Not sure if the fix has made it into a release yet or not. – R.. GitHub STOP HELPING ICE Jun 13 '14 at 20:51
  • Fix doesn't seem to be in GCC 4.8. It is in 5.2 however. – davidA Mar 22 '16 at 12:22
  • Is this merely a cosmetic bug (ie: just triggers a false warning in the build output; guess it's a big bug if you set `-Werror`), or does this bug also affect how code is actually compiled? – Cloud Oct 30 '16 at 16:12
  • 2
    @DevNull: It doesn't affect how code is compiled. Rather it affects how code is written, i.e. people either write non-portable constructs (`{}`) or write the "right" number of nesting levels to match a particular version of the structure definition, in order to make the warning go away. Warnings that cause people to write *worse code* to suppress the warning are some of the most harmful warnings a compiler can have. – R.. GitHub STOP HELPING ICE Oct 31 '16 at 19:15
29

Since your first member in the structure is an array you need:

static pkt_t stats = {{0}};

Outer braces are for the struct, inner braces are for the array. However, there are many other ways to skin this cat. (for instance, statics are already init'ed to zero)

Josh Petitt
  • 9,371
  • 12
  • 56
  • 104
7

If it is a global variable or a local static one, it's automatically initialized. So, simply:

static pkt_t stats;
Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
  • Good catch. This will also (not specified by the standard, but this is how it works in all real-world situations) put the object in bss rather than data, reducing the executable file size. – R.. GitHub STOP HELPING ICE Jul 20 '12 at 23:40
4

One way is to initialize every member of the struct inside the braces, rather than relying on the implicit zero filling. For array members, you need another {} which is likely causing the warning. Another is to just disable the warning, though this isn't recommended as it can also catch legitimate bugs.

Antimony
  • 37,781
  • 10
  • 100
  • 107
  • 1
    Disabling the warning is the correct fix here. The warning is buggy and flags correct code, and there's basically nothing it would flag that's actually a bug... – R.. GitHub STOP HELPING ICE Jul 19 '12 at 19:14
  • The warning can be disabled just for that line of code, thereby ensuring the warning remains active for the rest of the project. – davidA Mar 22 '16 at 12:23
1

Set this gcc compiler flag: -Wno-missing-braces

Doug Null
  • 7,989
  • 15
  • 69
  • 148
1
#define FRAME_TYPE_MAX 3

typedef struct {
    uint32_t incoming[FRAME_TYPE_MAX];
    uint32_t outgoing[FRAME_TYPE_MAX];
    uint32_t timeouts;
    uint32_t crc_errors;
} pkt_t;

static pkt_t stats1= { .incoming={5,6,20},
                       .outgoing={0,0,0},
                       .timeouts=0,
                       .crc_errors=0
                       };

static pkt_t stats2= { {5,6,20},
                       {0,0,0},
                       0,
                       0
                       };

static pkt_t stats3= {{0}};

pkt_t stats4 ;   // global


int main(void)
{

    stats1.incoming[0]= 35;
    stats1.timeouts=25;
    stats2.incoming[2]=10;  
    stats3.outgoing[2]=10;  
    stats4.timeouts=10;
    for (;;);
    }
jarjan13
  • 11
  • 1
1

If you still have the joy being on a gcc version which omits this false warning, with a struct like this in the question you can avoid this problem with some simple restructuring like this:

typedef struct {
    uint32_t timeouts;
    uint32_t crc_errors;
    uint32_t incoming[FRAME_TYPE_MAX];
    uint32_t outgoing[FRAME_TYPE_MAX];
} pkt_t;

static pkt_t stats = {0};
0

From "info gcc"

As a GNU extension, GCC allows initialization of objects with static storage duration by compound literals (which is not possible in ISO C99, because the initializer is not a constant). It is handled as if the object was initialized only with the bracket enclosed list if the types of the compound literal and the object match. The initializer list of the compound literal must be constant. If the object being initialized has array type of unknown size, the size is determined by compound literal size.

 static struct foo x = (struct foo) {1, 'a', 'b'};
 static int y[] = (int []) {1, 2, 3};
 static int z[] = (int [3]) {1};

The above lines are equivalent to the following:

 static struct foo x = {1, 'a', 'b'};
 static int y[] = {1, 2, 3};
 static int z[] = {1, 0, 0};

You may be able to combine these initializers to allow gcc-specific initialization of your arrays without having to specify every element in the array. Or...you can set a flag and initialize it at runtime when necessary, or...you can discover whether the variable is in BSS or not and may be automatically zeroed (is this on the stack in a function or in global memory).

Seth Robertson
  • 30,608
  • 7
  • 64
  • 57