4

I have the following simple program:

int main()
{
    int x = 5;
    static int y = x;
    return (0);
}

Compiling it with gcc, it produces error for the line static int y = x; since "initializer element is not constant". I assume this is due to y being a static variable, whose storage location (data/bss) and initial value need to be known at compile time.

However, when compiling with g++, I don't get any errors and the program runs well (printing y prints 5).

My questions are:

  1. Is my assumption correct?
  2. If so, how come it is possible to make such initialization to a static variable in c++?
Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52
localhost
  • 461
  • 4
  • 19
  • working fine for me: https://godbolt.org/z/qc3f9r – The Philomath Jan 14 '21 at 09:40
  • @ThePhilomath That's the point, it works in C++, but not in C. – Yksisarvinen Jan 14 '21 at 09:41
  • @Yksisarvinen: OP mentioned `gcc`. I am using `gcc`. Did I miss something? – The Philomath Jan 14 '21 at 09:43
  • Yes ,you are right about the Static initialization, It happens at compile time. The static variables are initialized during compile time and put in the executable section of the code during runtime – Giriteja Bille Jan 14 '21 at 09:43
  • 1
    @ThePhilomath OP mentioned `gcc` and `g++`. Unfortunately, "GCC" is a common name for both, but `gcc` command builds C by default and `g++` builds C++. There's more to that difference, but I never delved into that really, so I can't explain it well. – Yksisarvinen Jan 14 '21 at 09:54

3 Answers3

7

Your program is well-formed in C++ as local variables with static storage duration are initialized not during startup (with some exceptions for constant expressions; not applicable in this example) but at the first time control passes through their declaration, at which point the initializer expression, containing the local non-static variable x, is readily available.

Citing cppreference / Storage duration - Static local variables [emphasis mine]

Variables declared at block scope with the specifier static or thread_local (since C++11) have static or thread (since C++11) storage duration but are initialized the first time control passes through their declaration (unless their initialization is zero- or constant-initialization, which can be performed before the block is first entered). On all further calls, the declaration is skipped.

Static initialization in C, however, does not follow the same rules; from cppreference / C language - Initialization:

When initializing an object of static or thread-local storage duration, every expression in the initializer must be a constant expression or string literal.

Thus your program is ill-formed in C.

dfrib
  • 70,367
  • 12
  • 127
  • 192
  • Thanks! If so, then where is y stored? BSS, I guess? – localhost Jan 14 '21 at 18:48
  • 1
    @Ben No, the `.bss` is typically for unitialized and zero-initialized static data. The storage for `y` should end up in the `.data` segment. – dfrib Jan 14 '21 at 19:19
5

In C++, static local variables are initialized only once at the first time control passes through their declaration. For this case, y is initialized after main() is invoked, and x has been initialized with value 5, then y is initialized as 5 too.

are initialized the first time control passes through their declaration

In C, static variables are initialized prior to program startup, i.e. before main() is invoked; y can't be initialized from local variable x in main().

Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
-1

My guess would be that this is a different compiler interpretation of https://en.cppreference.com/w/cpp/language/storage_duration#Static_local_variables

Usually, you can only assign static values to static variables. This includes the .data section of your executable (e.g. all char*/c-style strings are static by nature).

Since x is not a static value, gcc complains rightfully so. G++ is the c++-compiler and therefore has a different implementation to gcc, which is C by default.

Lithium
  • 69
  • 3