C Static Array Initialization - how verbose do I need to be?

10,316

Solution 1

int foo[10] = {0};

This is very fine :)


Note that if you do the following:

int foo[10] = {1};

Only the first element of the array will be initialized with the non-zero number whereas the rest will be initialized with zeros.

Solution 2

In C/C++ if you initialize just the first element of an array of known size with a value, the remainder will be zero-filled, so:

int foo[10] = {0};

will do exactly what you want.

This also works for structs:

struct bar {
    int x;
    int y;
    char c;
} myBar = {0};

will initialize all members to 0.

The standard (C99 - 6.7.8/12 - Initialization) says this:

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.

In C the grammar requires that there be at least one 'assignment-expression' inside the braces. An 'assignment-expression' can be many things from a constant or identifier up through much more complex expressions. However, an empty string doesn't qualify as an 'assignment-expression', so there has to be something between the braces.

In C++, the grammar specifically allows the '{ }' initializer, so the following would also zero-initialize the array:

int foo[10] = {};

It's probably also worth noting that in C++ the entries that don't have a specific initializer value in the initialize list will be 'value-initialized' or 'default-initialized' which might be different than being zero-initialized depending on what the constructors for the variable type are and whether the compiler is following the C++98 standard or the C++03 standard (this is probably the only difference of any significance between C++98 and C++03). The whole situation with value vs. default initialization is rather complicated, so if you're interested see this answer: Do the parentheses after the type name make a difference with new?.

Fortunately, the difference doesn't seem to cause much trouble in practice, although if you run into it, it would probably cause some head scratching for a while when trying to figure out what the behavior really should be. I usually don't really think much about it - it makes my head hurt.

Share:
10,316
jgottula
Author by

jgottula

Updated on June 16, 2022

Comments

  • jgottula
    jgottula almost 2 years

    To initialize an int array with all zeros, do I need to use:

    int foo[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    

    Or, will this work:

    int foo[10] = {0};
    
  • UncleBens
    UncleBens over 14 years
    From that rule it should follow that even int foo[10] = {}; is enough for an array of 10 zeros.
  • Michael Burr
    Michael Burr over 14 years
    @UncleBens - in C the grammar requires that there be at least one 'assignment-expression', which can be many things from a constant or identifier up through a more complex expression. However, an empty string doesn't qualify as an 'assignment-expression', so there has to be something between the braces. The C++ grammar specifically allows the '{ }' initializer.
  • Khaled Alshaya
    Khaled Alshaya over 14 years
    @digitalross If you don't initialize an auto aggregate at all, then yes it shall contain garbage. The question is what if you initialize an aggregate with {0} either it is an auto or it isn't.
  • mmx
    mmx over 14 years
    @digitalross: You are wrong. If you leave locals completely uninitialized, it'll be uninitialized. If you use an initializer and initialize any one of fields, every field will be initialized.
  • Michael Burr
    Michael Burr over 14 years
    @digitalross: this is covered by the paragraph "If there are fewer initializers ... the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration."
  • Jingguo Yao
    Jingguo Yao almost 12 years
    C99 standard disallows {}. C++11 standard allows {}. gcc with -std=c99 allows {}. gcc with -pedantic disallows {}.