I was wondering if someone could provide a detailed, simple explanation of the differences between the two of the following pieces of code. Given the following definition:
typedef struct {
stuff;
stuff_2;
} variable_t;
What is the difference between:
variable_t my_variable;
variable_t my_variable = {};
And if I do the first one, and then never fully initialize it, why does the compiler not throw an error?
Note: I am compiling with gcc -std=gnu99
, so the second is valid and wound up being the solution to a problem that I had. I was wondering as to why.
It depends a little bit on where you place the respective variable definition, and it also seems depends on the compiler in use.
Automatic storage duration
Let's discuss the difference when the variables have automatic storage duration (which is the case if you place it in function or block scope and there without static
keyword):
void someFunction() {
variable_t my_variable; // (1)
variable_t my_variable = {}; // (2)
}
(1) denotes a variable definition without an explicit initialization. And according this online C standard draft, it's value is indeterminate:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.
(2) is a variable definition with explicit initialization through an initializer list without designators, i.e. without associating values to members through their names but only through the order of values (cf. 6.7.9 p17..21).
The interesting paragraph is 6.7.9 p21, which states that if the initializer list has fewer entries than the number of struct members, the members are initialized according to the initialization rule of static storage duration (i.e. to 0
or NULL
as explained later):
If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, ... , the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.
So it seems that if you write variable_t my_variable = {}
, then all members are initialized to 0
or NULL
.
However, as mentioned by aschepler in the comments, C initialization list grammar states that initializer lists must not be empty (cf. also cppreference.com):
... the initializer must be a non-empty, brace-enclosed, comma-separated list of initializers for the members
So according to the standard an initializer list in C needs at least one entry; When testing it in my XCode8.3 environment with -std=gnu99
, an empty initialization list seems to be supported, but I am aware that this is not a valid reference. So to be safe and not to depend on particular compiler extensions, you should actually write:
variable_t my_variable = {0};
Static storage duration
At file scope, your variable definitions will have static storage duration, and then other rules apply (cf. 6.7.9 (10)):
(10) ... If an object that has static or thread storage duration is not initialized explicitly, then:
- if it has pointer type, it is initialized to a null pointer;
- if it has arithmetic type, it is initialized to (positive or unsigned) zero;
- if it is an aggregate, every member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;
- if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;
...
(21) If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, ... the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.
So if you write...
#include <stdio.h>
variable_t my_variable; // (1)
variable_t my_variable = {}; // (2)
then (1) and (2) actually yield the same result because for the not explicitly initialized variable (1), paragraph (10) applies, and for the explicitly but empty initialized variable (2), according to paragraph (21), every member falls back to the initialization rule of (10).
Again, compilers may not support empty initalization lists as discussed above.
Hope it helps (because it has been a lot of typing :-) )