Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens to initialization of static variable inside a function

Tags:

c

static

After stumbling onto this question and reading a little more here (c++ but this issue works the same in C/C++ AFAIN) I saw no mention to what is realy happening inside the function.

void f(){
  static int c = 0;
  printf("%d\n",c++);
}

int main(){
  int  i = 10;
  while(i--)
    f();
  return 0;
}

In this snippet, c lifetime is the entire execution of the program, so the line static int c = 0; has no meaning in the next calls to f() since c is already a defined (static) variable, and the assignment part is also obsolete (in the next calls to f()), since it only takes place at the first time.

So, what does the compiler do? does it split f into 2 functions - f_init, f_the_real_thing where f_init initializes and f_the_real_thing prints, and calls 1 time f_init and from that onward, only calls f_the_real_thing?

like image 380
CIsForCookies Avatar asked Dec 03 '22 12:12

CIsForCookies


2 Answers

The first assignment is not "obsolete" - it ensures c is zero the first time f() is called. Admittedly that is the default for statics: if no initialiser is specified, it will be initialised to zero. But a static int c = 42 will ensure c has the value 42 the first time the function is called, and the sequence of values will continue from there.

The static keyword means that the variable has static storage duration. It is only initialised once (so will have that value the first time the function is called) but changes then persist - any time the value is retrieved, the value retrieved will be the last stored in the variable.

All the compiler does is place the variable c into an area of memory that will exist - and hold whatever value it was last set to - for as long as the program is running. The specifics of how that is achieved depends on the compiler.

However, I have never seen a compiler that splits the logic of the function into multiple parts to accommodate the static.

like image 176
Peter Avatar answered May 04 '23 01:05

Peter


Although the standard does not dictate how compilers must implement behavior, most compilers do a much less sophisticated thing: they place c into static memory segment, and tell the loader to place zero into c's address. This way f comes straight to pre-initialized c, and proceeds to printing and incrementing as if the declaration line where not there.

In C++ it optionally adds code to initialize c to static initialization function, which initializes all static variables. In this case, no call is required.

In essence, this amounts to c starting its lifetime before the first call to f. You can think of c's behavior as if it were a static variable outside f() with its visibility constrained to f()'s scope.

like image 35
Sergey Kalinichenko Avatar answered May 03 '23 23:05

Sergey Kalinichenko