tags:

views:

3998

answers:

8

When {0} is used to initialize an object in C/C++, what does it mean? I can't find any references to {0} anywhere, and because of the curly braces Google searches are not helpful.

Example code:

SHELLEXECUTEINFO sexi = {0};
sexi.cbSize = sizeof(SHELLEXECUTEINFO);
sexi.hwnd = NULL;
sexi.fMask = SEE_MASK_NOCLOSEPROCESS;
sexi.lpFile = lpFile.c_str();
sexi.lpParameters = args;
sexi.nShow = nShow;

if(ShellExecuteEx(&sexi))
{
 DWORD wait = WaitForSingleObject(sexi.hProcess, INFINITE);
 if(wait == WAIT_OBJECT_0)
  GetExitCodeProcess(sexi.hProcess, &returnCode);
}

Without it, the above code will crash on runtime....

Thanks.

+89  A: 

What's happening here is called aggregate initialization. Here is the (abbreviated) definition of an aggregate from section 8.5.1 of the ISO spec:

An aggregate is an array or a class with no user-declared constructors, no private or protected non-static data members, no base classes, and no virtual functions.

Now, using {0} to initialize an aggregate like this is basically a trick to 0 the entire thing. This is because when using aggregate initialization you don't have to specify all the members and the spec requires that all unspecified members be default initialized, which means set to 0 for simple types.

Here is the relevant quote from the spec:

If there are fewer initializers in the list than there are members in the aggregate, then each member not explicitly initialized shall be default-initialized. Example:

struct S { int a; char* b; int c; };
S ss = { 1, "asdf" };

initializes ss.a with 1, ss.b with "asdf", and ss.c with the value of an expression of the form int(), that is, 0.

You can find the complete spec on this topic here:

http://www.kuzbass.ru:8086/docs/isocpp/decl.html#dcl.init.aggr

Don Neufeld
Excellent response. Just wanted to add that initialising an aggregate with {0} is the same as initialising it with simply {}. Perhaps the former makes it more obvious that built-in types get zeroed.
James Hopkin
Some compilers choke on {}, that's why {0} gets used
Branan
Not quite.. In C++, if the first member cannot be zero-constructed then {0} will not work. Ex: struct A { B b; int i; char c; }; struct B { B(); B(string); }; A a = {}; // this statement cannot be rewritten as 'A a = {0}'.
Aaron
@Branan, that's because in C "{}" isn't valid. In C++ it is. @don.neufeld, this has changed with C++03 (default-initialized -> value-initialized). The quote cites the C++98 Standard, bear in mind.
Johannes Schaub - litb
+2  A: 

It's been awhile since I worked in c/c++ but IIRC, the same shortcut can be used for arrays as well.

BioBuckyBall
+5  A: 

I also use it to initialize strings eg.

char mytext[100] = {0};
Adam Pierce
Though, of course, if mytext is being used a string, char mytext[100]; mytext[0] = '\0'; would have the same effect of giving an empty string, but only cause the implementation to zero the first byte.
Chris Young
+37  A: 

One thing to be aware of is that this technique will not set padding bytes to zero. For example:

struct foo
{
    char c;
    int  i;
};

foo a = {0};

Is not the same as:

foo a;
memset(&a,0,sizeof(a));

In the first case, pad bytes between c and i are uninitialized. Why would you care? Well, if you're saving this data to disk or sending it over a network or whatever, you could have a security issue.

Harold Ekstrom
yep, should be:struct foo a = {0};
Nathan Fellman
Aaron
Also, if you are sending stuff across the network you will always set the alignment to be packed. That way you get as few extra padding bytes as possible.
excellent point about avoiding an information leak...
ceretullis
It should be noted that although the spec does not require the padding to be initialized, any sane compiler will, as it only costs time to initialize "around" it.
Tomas
+7  A: 

Note that an empty aggregate initializer also works:

SHELLEXECUTEINFO sexi = {};
char mytext[100] = {};
dalle
A: 

Recently I saw some code that used the following:

int i = {0};
double l = {-1.0};

which seems totally odd to me.

In this case at least, it looks like the curly braces were just there for fun?

tfinniga
+2  A: 

In answer to why ShellExecuteEx() is crashing: your SHELLEXECUTEINFO "sexi" struct has many members and you're only initializing some of them.

For example, the member sexi.lpDirectory could be pointing anywhere, but ShellExecuteEx() will still try to use it, hence you'll get a memory access violation.

When you include the line:

SHELLEXECUTEINFO sexi = {0};

before the rest of your structure setup, you're telling the compiler to zero out all structure members before you initialize the specific ones you're interested in. ShellExecuteEx() knows that if sexi.lpDirectory is zero, it should ignore it.

snowcrash09
A: 

This is a generic way to initialize both aggregate and scalar auto types. Details here: http://pixelbeat/programming/gcc/auto_init.html

pixelbeat