From “C++ Primer, 5th Edition”, page 407:
All static duration variables share the following two initialization
features:
An uninitialized static variable has all its bits set to 0.
A static variable can be initialized only with a constant expression.
A constant expression can use literal constants, const and enum
constants, and the sizeof operator. The following code fragment
illustrates these points:int x; // x set to 0 int y = 49; // 49 is a constant expression int z = 2 * sizeof(int) + 1; // also a constant expression int m = 2 * z; // invalid, z not a constant int main() {...}
My question is – WHY is this the standard? What is the (practical) reason for this.
What harm would have befallen us otherwise?
Especially, I find it hard to come up with a reason for the invalidity of:
int m = 2 * z; // invalid, z not a constant
since z itself is already known at compilation time.
Answer:
Simply put, according to the standard it is not guaranteed that instructions before the first statement of main will be done in order.
It is guaranteed though that all static storage will be zero-initialized before any other initialization.
This means that in the example I gave: int m = 2 * z; is an undefined behavior and m might either evaluate to 2*0=0 or it might be evaluated to `2*(2 * sizeof(int) + 1).
Out of the “C++ Standard – ANSI ISO IEC 14882 2003” 3.6.2 (p.44):
Objects with static storage duration (3.7.1) shall be zero-initialized
(8.5) before any other initialization takes place.…
An implementation is permitted to perform the initialization of an
object of namespace scope with static storage duration as a static
initialization even if such initialization is not required to be done
statically……
And the important bit:
As a consequence, if the initialization of an object obj1 refers to an
object obj2 of namespace scope with static storage duration
potentially requiring dynamic initialization and defined later in the
same translation unit, it is unspecified whether the value of obj2
used will be the value of the fully initialized obj2 (because obj2 was
statically initialized) or will be the value of obj2 merely
zero-initialized.`
Further reading about problems of this sort:
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14
Edit: Put in answer. Pubby’s was the correct answer (and got accepted) but I really missed the “As a consequence..” part. Also, I think the link I added might be useful.
Static initialization (technically constant initialization) requires constant expressions, but static storage duration variables do not.
Dynamic initialization can rely on functions and other things that can’t be decided at compile time. The compiler is allowed to perform static initialization if it can determine the result.
The example you posted will work, although it can lead to trouble with more complicated initialization, as some variables can be initialized dynamically or statically: