tags:

views:

318

answers:

4

Hi, 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?

Thanks for your time.

P.S.: Sorry for the title, I couldn't think of a better one.

A: 

You need one initializer per field of STARTUPINFO. It probably has more than one field.

Keith Randall
Doesn't aggregate initialization fill up missing values with `0`? Or does this only apply to array initializers?
sbi
@Keith {0} is aggregate initializer as sbi said. {0} initializes all elements to zero.
AraK
No, aggregate initializers only work for arrays, not structures. Compile this, with g++ -Wall -Wextrastruct foo { int a; int b;} c = {0};
Keith Randall
From the standards: **8.5.1 Aggregates** it says: An aggregate is an array or a class (clause 9) with no user-declared constructors (12.1), no private or protected non-static data members (clause 11), no base classes (clause 10), and no virtual functions (10.3).
AraK
The Standard (the C Standard) has 7 sections. There is no **section 8.5.1**.
pmg
@pmg my bad I got it from the C++ standards :)
AraK
ok, then the compiler is warning about something that is technically well-defined by the standard, but is nonetheless possibly not what you wanted. You did ask for -Wextra, after all...
Keith Randall
+3  A: 

Using {0} will initialize all the fields of the struct to zero, but if the compiler adds padding then padding bytes will not be initialized. Using memset will initialize all bytes with the inserted padding. memset is something like blind initializing.

AraK
If that's the case (and IMO it seems likely), then to me this seems quite a stupid warning.
sbi
Also, but probably not relevant in this case, initialization with {0} might be different from memset, as the former initializes to 0, and memset sets the value to all-bits-0, which on some architectures is not the same thing as floating-point 0 or pointer 0.
jk
+4  A: 

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:

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 default 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.

Michael Burr
+1 I think this is *the* answer :)
AraK
GCC also accepts the empty braces (`{}`) as an extension to the C language.
FX
A: 

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