Only when the value is not known at compile time.
Not quite. With respect to local static entities, only zero-initialization is guaranteed to occur before the program entry point is run (main).
The zero-initialization (8.5) of all block-scope variables with static storage duration (3.7.1) or thread storage duration (3.7.2) is performed before any other initialization takes place.
As opposed to constant-initialization:
Constant initialization (3.6.2) of a block-scope entity with static storage duration, if applicable, is performed before its block is first entered.
This means it can happen anywhere, be it before main is run, or anywhere in between main and the start of the block.
If the compiler decides to optimize the initialization to match that of a non-local static, it is free to do so, but is not a requirement. And is not a portable assumption to make. Static initialization ordering isn’t called a ‘fiasco’ for nothing.
An implementation is permitted to perform early initialization of other block-scope variables with static or thread storage duration under the same conditions that an implementation is permitted to statically initialize a variable with static or thread storage duration in namespace scope (3.6.2).
And everything that is not ‘applicable’ or dynamic:
Otherwise such a variable is initialized the first time control passes through its declaration