Why is the compiler throwing this warning: "missing initializer"? Isn't the structure initialized?
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?
Solution 1:
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:
- http://gcc.gnu.org/ml/gcc-bugs/1998-07/msg00031.html
- http://gcc.gnu.org/ml/gcc-bugs/1998-07/msg00059.html
- http://gcc.gnu.org/ml/gcc-bugs/1998-07/msg00128.html
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 esentially 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.
Solution 2:
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
Solution 3:
You asked for as many warnings as possible using
-Wall -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
Solution 4:
This web page discusses the underlying issue in great detail: http://ex-parrot.com/~chris/random/initialise.html
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.
Solution 5:
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;