87

I'm creating some sort of frontend for a program. To launch the program I'm using the call CreateProcess(), which among other things receives a pointer to a STARTUPINFO structure. To initialize the structure I used to do:

STARTUPINFO startupInfo = {0}; // Or even '\0'.
startupInfo.cb = sizeof(startupInfo);

When compiling the program with GCC enabling these sets of warnings -Wall -Wextra it gives me a warning saying that there's a missing initializer pointing to the first line.

warning: missing initializer
warning: (near initialization for 'startupInfo.lpReserved')

So I ended up doing:

STARTUPINFO startupInfo;
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);

And this way the compiler doesn't give any warning. The question is, what is the difference between these ways of initializing a structure? Using the first method, isn't the structure initialized? Which one would you recommend?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shantia
  • 1,129
  • 2
  • 9
  • 9
  • 1
    The warning is just that: a warning. It's ok to ignore this specific warning on this specific occasion. The compiler emits the warning to help you in cases like: `struct struct_with_four_fields x = {1, 2, 3};` where only 3 out of 4 members are initialized. – pmg Oct 08 '09 at 17:02
  • In my previous comment the 4th member is initialized to 0. – pmg Oct 08 '09 at 17:03
  • 5
    Warning about missing initializers is not unreasonable in general; if you have a structure with 4 members and you provide initializers for only 3 of them, it's likely to be a mistake. But `{ 0 }` is a common and well-defined idiom for initializing all members to zero (defined recursively for each sub-member) -- which is why later versions of gcc have been modified not to warn about that particular case. – Keith Thompson Sep 09 '13 at 17:24
  • @KeithThompson what're you talking about? [I am using gcc 4.8.2](https://gcc.gnu.org/ml/gcc/2014-09/msg00123.html), and since the question five years passed. P.S. there was one more mail, which I am wanted to link in the end, but to my wonder it is missing. Probably mail server do not save all the messages, that's sad, the mail would be useful to one who meet the problem again. – Hi-Angel Sep 12 '14 at 10:07
  • @Hi-Angel: I don't understand what you're asking. – Keith Thompson Sep 12 '14 at 14:47
  • @KeithThompson you told that this bug was fixed. I just showed that this is not true. – Hi-Angel Sep 12 '14 at 20:27
  • 4
    @Hi-Angel: When I compile a small program with gcc-4.8.1 on Solaris, I get "warning: missing initializer". When I compile the same program with gcc-4.8.2 on Linux Mint, I don't get a warning. Incidentally, the line `obj = {0};` in the [message you linked to](https://gcc.gnu.org/ml/gcc/2014-09/msg00123.html) is not valid C, and gcc 4.8.2 rejects it as a syntax error. If you're compiling as C++, remember that it's a different language, and gcc uses a different front end; fixes in gcc's C compiler may or may not apply to g++. – Keith Thompson Sep 12 '14 at 20:41

5 Answers5

91

GCC is just being overly paranoid - for no good reason in my opinion, but then it's certainly true that the GCC maintainers know a lot more about the nuances of C that I do.

See this small thread of discussion about the problem on the GCC mailing list:

The bottom line though - initializing the struct with just {0} will in fact zero initialize the whole thing.

The C99 standard says the following in 6.7.8/21 "Initialization - Sematics":

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

C90 says essentially the same in 6.5.7 with a bit different wording (in other words, C99 didn't add something new here).

Also note that in C++ this was extended so that an empty set of braces, "{}", would perform value initialization on an object because there were situations (like templates) when you wouldn't even know what the members or how many members a type might have. So not only is it good practice, but necessary at times to have an initializer list that's shorter than the number of members an object might have.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • GCC also accepts the empty braces (`{}`) as an extension to the C language. – F'x Oct 08 '09 at 18:10
  • 19
    I had to add `-Wno-missing-field-initializers` and `-Wno-missing-braces` so that GGC stopped moaning about me putting `= {0};` for my structures. Does anyone know if disabling these warning will miss warnings for other things other than `= {0};` for structures? – Matt Clarkson Aug 09 '11 at 18:30
  • Using those options will suppress warnings at times other than using `{0}`: `-Wno-missing-field_initializers` will prevent a warning being generated if you start to init a struct, but don't have explicit initializers for all fields. `-Wno-missing-braces` will suppress a warning if you init a struct that has nested struct subobject, but don't 'nest' the subobject init in braces. I think it would be legit for people to want warnings in those situations but not for `{0}`. It's too bad that GCC doesn't make some sort of exception for the `{0}` idiom (even if it had to be enabled with an option). – Michael Burr Aug 09 '11 at 23:13
  • Looks like this bug was fixed in revision [172857](http://gcc.gnu.org/viewcvs?view=revision&revision=172857). Does anyone know how to find out if this change ever got integrated into a release? – splicer May 18 '12 at 10:47
  • 4
    The fix is present in [gcc 4.7.0](http://gcc.gnu.org/viewcvs/tags/gcc_4_7_0_release/gcc/c-typeck.c?view=co), but not [gcc 4.6.3](http://gcc.gnu.org/viewcvs/tags/gcc_4_6_3_release/gcc/c-typeck.c?view=co). – splicer May 18 '12 at 11:13
  • 1
    @splicer: Which "the" fix? Also I am compiling with `mingw32-g++.exe (GCC) 4.7.2` and getting this warning on the idiom above (even the exact case of `STARTUPINFO`). – Jan Hudec May 15 '13 at 12:28
  • 2
    @Jan Hudec: Revision [172857](http://gcc.gnu.org/viewcvs/gcc?view=revision&revision=172857). Unfortunately, the URLs from my previous comments no longer work. Here's the bug associated with the fix: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750 – splicer May 28 '13 at 00:20
  • 9
    I'm still getting the warning even with gcc 4.9.3 when using the empty brace `{}` or `{0}` initializers in my C++ classes :/ – Kamil Kisiel Jul 04 '15 at 06:39
  • 1
    Hilarious, the bug report was from 1998, and it's still not fixed in 2016. – Leandros Apr 21 '16 at 18:22
  • https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61489 was seemingly fixed in a version, 5.1(.0?), released 2015-04-22. – Martin Dorey Aug 21 '23 at 23:04
26

This can be easily fixed for GCC in C++ programs by initializing the structure as

STARTUPINFO startupInfo = STARTUPINFO();
  • just did exactly this a few days ago
dmityugov
  • 4,390
  • 23
  • 18
  • 2
    A possible pitfall with this answer is that in C++98 this did not zero-initialize the fields. The zero-initialization behaviour was added in C++03. – M.M Apr 16 '17 at 13:56
  • 1
    @M.M Thank you for pointing out the possible pitfall but I think in December 2018 this shouldn't be in the code any more any dangerous situation. BTW, I find this answer the best! – Peter VARGA Dec 05 '18 at 18:28
  • @AlBundy Unfortunately there are still some compilers around that use C++98 initialization (e.g. C++Builder XE5 32-bit mode which I have open right now coincidentally) – M.M Dec 05 '18 at 21:30
  • I had to add 10+ lines of code to my file because of this. I am really angry. Tried to pass anonymous objects in a function call. If I used {} or {0} I got this warning (treated as an error). If I used () then gcc thinks it is a function call... – bencemeszaros Apr 16 '19 at 08:34
17

You asked for as many warnings as possible using -Wall and -Wextra.

In this case, you get a warning that tells you you didn't specify all fields, which is perfectly valid, but could have been unintentional.

You can suppress this warning by adding -Wno-missing-field-initializers.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ecotax
  • 1,933
  • 17
  • 22
14

The web page How to initialise structures to all-elements-zero-or-null discusses the underlying issue in great detail:

As a work-around, my current solution is to selectively suppress this warning:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
STARTUPINFO startupInfo = {0};
#pragma clang diagnostic pop

Sadly, this only works in Clang and doesn’t seem to work in GCC.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JanX2
  • 1,303
  • 1
  • 12
  • 19
  • 4
    I can confirm: `#pragma GCC diagnostic ignored "-Wmissing-field-initializers"` accepted by GCC compiler 4.2.1 but do nothing. unsure about new versions of gcc – Maxim Kholyavkin Oct 10 '14 at 08:00
  • 1
    @speakus, I can confirm it is working with the lastest (at time of write) gcc (7.3.0). – cydef Feb 19 '18 at 09:19
  • @cydef according to other comments and to the bug reports I've seen, GCC no longer warns (as of GCC 5) for this at all -- regardless of `#pragma clang diagnostic ignored "-Wmissing-field-initializers"`. You should probably check if this is the case. – WD40 Mar 30 '18 at 18:10
1

In C++ you can use boost::initialized_value to get rid of this warning. I have warnings turned off for boost; so I don't know if this would cause any other warnings in your case. This way you don't have to disable the warning.

Example:

T bla = boost::initialized_value;
Mat
  • 202,337
  • 40
  • 393
  • 406
  • But this presumes use of [Boost](https://en.wikipedia.org/wiki/Boost_%28C%2B%2B_libraries%29)(?). Is this covered by the standard library in some version? – Peter Mortensen Jul 27 '22 at 01:54
  • OK, the OP has left the building (*"Last seen more than 2 years ago "*). Perhaps somebody else can chime it? – Peter Mortensen Jul 27 '22 at 01:56