The specific rule that applies here is C 2018 6.7.9 4:
All the expressions in an initializer for an object that has static or thread storage duration shall be constant expressions or string literals.
The primary reason for this arises from the way that C is typically implemented, with a compiler generating object modules (which are later linked into executables and run). In such a C implementation, initializing an object with static storage duration requires the compiler to know the initial value, whereas initializing an object with automatic storage duration does not require the compiler to know the initial value.
This is because, to initialize an object with static storage duration, the compiler must put the initial value into the object module being generated. To initialize an object with automatic storage duration, the compiler merely needs to generate instructions to get or calculate the initial value and store it in the object.
When int a = 5;
and int b = a;
appear outside of any function, a
and b
have static storage duration. At this point, the compiler could, in theory, see that a
was initialized with the value five, so it has that value when used in int b = a;
. However, there are some issues with this:
- It requires the compiler to maintain knowledge about objects it is not currently required to maintain.
- It can only be done in certain circumstances, as when the initializer for
b
uses only objects that have been initialized earlier in the same translation unit. Extending the language to require the compiler to support this would require more complicated rules.
- It requires extending the language semantics to specify what values objects have before the program is executed at all.
Another possibility would be that, to make initializations like int b = a;
work, the compiler does it by generating instructions to be executed when the program starts, possibly immediately before main
is called. This adds complications, including:
- If
int b = a;
appears in a translation unit other than the one containing main
, how is the code necessary to initialize b
inserted in main
or in the program start-up code?
- When there are multiple such initializations, some of which may depend on each other, how do you ensure they are executed in the desired order?
These problems could be solved, in theory, but C is intended to be a “simple” language.