Search code examples
cstatic-variablesvariable-initialization

Are uninitialized members of partially-defined static objects guaranteed initialized to 0?


I know that uninitialized static variables are stored in BSS and therefore guaranteed to be initialized with all 0 (for their respective data-type size).

Also, in C, static variables can be defined to compile-time constants (only).

What is the defined behavior of "partially initialized" static variables (I'm not sure if that is the correct term), as exampled by the following:

// main.c

#include <stdbool.h>
#include <stdio.h>

static struct Foo
{
  bool f[2][3];
} g_table =      { { { true, true, false },
                     { true } } };

int main( int argc, char* argv[] )
{
  printf( "%d %d %d\n", g_table.f[0][0], g_table.f[0][1], g_table.f[0][2] );
  printf( "%d %d %d\n", g_table.f[1][0], g_table.f[1][1], g_table.f[1][2] );
  return 0;
}

.

$ gcc --version && gcc -g ./main.c && ./a.out 
gcc (GCC) 9.2.1 20190827 (Red Hat 9.2.1-1)
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

1 1 0
1 0 0

By "partially initialized," above, I mean to refer to the initialization of g_table, where not all elements of the member array are explicitly defined. The above example implies that the not-explicitly-initialized parts of static object g_table are initialized to 0. Is this guaranteed/defined behavior?


Note: I'm aware there are existing Stack Overflow questions regarding static variable initialization and the default value of uninitialized static variables; I was unable to find an existing question regarding this "partial initialization" (please let me know if there is an existing, more correct term for what I'm describing).


Solution

  • All remaining elements are initialized to zero (for arithmetic types) or a null pointer (for pointers). C 2018 6.7.9 21 says:

    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.

    6.7.9 10 says objects with static storage duration are, effectively, initialized with zero:

    … 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;