0

file1.cpp

#include <iostream>

extern int u;
int i=9;
int j=i+9;
int main()
{
   std::cout<<u;
   return 0;
}

file2.cpp

extern int j;
int u=j+9;

Result is u=9 but not 27

This shows that j is initialized twice - First zero(due to which variable u get value 9) and then with 18

Is it possible ?? My meaning for initialization is destroyed here.

I also try to make variable j constant to see what will happen next

file1.cpp //after changing j to constant

extern int u;
int i=9;
extern const int j=i+9;

This has same output as before.

However if I change int j=i+9;(in file1.cpp) to int j=9;

Surprisingly, I got correct values i.e. u=18;

CharlesB
  • 86,532
  • 28
  • 194
  • 218
T.J.
  • 1,466
  • 3
  • 19
  • 35

4 Answers4

4

The order of initialization of global variables declares across different translation Units is not specified.

The globals u and i, j reside in different translation units in your code, so the order whether u gets initialized first or i & j get initialized before u is Unspecified.
This invokes an Undefined Behavior in your code.
This invokes an Unspecified Behavior in your code

However, Note that order of initialization of globals in the same translation unit is well-defined.
i.e: it is well defined that i will be initialized before j in your code.

What you are seeing is a classic case of Static Initialization Fiasco.

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 1
    There's no undefined behavior, because zero initialization is guaranteed to precede any dynamic initialization. On the other hand, it's unspecified whether `j` is used before its dynamic initialization or after: it will be either `0` or `18`, but it is impossible to know which. – James Kanze Feb 17 '12 at 09:48
  • @JamesKanze: Yes agreed. The globals will be zero initialized, theres no UB but an Unspecified value being used. – Alok Save Feb 17 '12 at 09:51
2

Because "i" is not "const int", i+9 is not a constant expression. That makes it so that the initialization of "j" is dynamic. The one of "u" is too. The order of the dynamic initializations of "u" and "j" is undefined. So you dont know which value will be used for "u". In your case you get the value of "j" that was the result of zero initialization but before it was dynamically initialized, so "j" was still zero.

If you make "i" a "const int" then you should get the correct value into "u", since "j" will then be initialized statically.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
1

The order in which global variables are initialized in different translation units are not defined. So if you initialize a global variable with another global variable, where the variables are in different translation units, what will happen isn't defined it is not guaranteed that the variables will be initialized properly, and should be avoided.

Donotalo
  • 12,748
  • 25
  • 83
  • 121
  • Each global variable is initialized only once, but if you access them before they're initialized, bad things can happen. – David Schwartz Feb 17 '12 at 09:43
  • Nearly true. The order *between different translation units* is not defined. If the two globals are in the same TU, their order of initialization is well-defined – jalf Feb 17 '12 at 09:43
  • Thats not the full story. Variables with static storage duration are zero initialized before everything else, in this case dynamic intialization. Within one translation unit, this initialization is ordered in the order of the definition in that translation unit. What is the problem here is that variables in different translation units depend on each other, and the order of initialization among different TUs is what is the problem here. – PlasmaHH Feb 17 '12 at 09:45
1

That's what the standard says should happen. All static objects are zero initialized before anything else happens. Then comes all static initialization, then all dynamic initialization. Within a translation unit, initialization occurs in the lexical order of the definitions; between translation units, the order is unspecified, so whether the (dynamic) initialization of u comes before or after the dynamic initialization of j may vary; changing the order you specify the files on the command line could change the behavior of your code.

If the initialization is with a constant expression, then it becomes static initialization. For an expression to be considered a constant expression, all variables in it must be const, must be themselves initialized with a constant expression, and their initializers must be visible. In your case, making all of the variables const will mean that j has static initialization, but it won't do anything for u, because the initializer for j isn't visible in file2.cpp.

James Kanze
  • 150,581
  • 18
  • 184
  • 329