Tags C & C++

Consider this code:

int init_func()
{
    return 42;
}


int global_var = init_func();


int main()
{
    return global_var;
}

Is it valid C? Is it valid C++?

Curiously, the answer to the first question is no, and to the second question is yes. This can be easily checked with a compiler:

$ gcc -Wall -pedantic global_init.c
global_init.c:7: error: initializer element is not constant

$ g++ -Wall -pedantic global_init.c
$ a.out; echo $?
42

The C standard prohibits initialization of global objects with non-constant values. Section 6.7.8 of the C99 standard states:

All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.

What is an object with static storage duration? This is defined in section 6.2.4:

An object whose identifier is declared with external or internal linkage, or with the storage-class specifier static has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.

C++ is a different story, however. In C++ much more is being determined at runtime before the user's main function runs. This is in order to allow proper construction of global and static objects (C++ objects may have user-defined constructors, which isn't true for C).

Peeking at the disassembled code produced by the g++ for our code snippet, we see some interesting symbols, among them __do_global_ctors_aux and _Z41__static_initialization_and_destruction_0ii, both executed before our main.

In particular, _Z41__static_initialization_and_destruction_0ii does the actual initialization of global_var. Here are the relevant lines:

40055d:  callq  400528 <_Z9init_funcv>
400562:  mov    %eax,2098308(%rip) # 6009ec <global_var>

init_func is called (its name is distorted due to C++ name mangling), and then its return value (which is in eax) is assigned to global_var.