What Makes a Static Variable Initialize Only Once

What makes a static variable initialize only once?

Yes, it does normally translate into an implicit if statement with an internal boolean flag. So, in the most basic implementation your declaration normally translates into something like

void go( int x ) {
static int j;
static bool j_initialized;

if (!j_initialized) {
j = x;
j_initialized = true;
}

...
}

On top of that, if your static object has a non-trivial destructor, the language has to obey another rule: such static objects have to be destructed in the reverse order of their construction. Since the construction order is only known at run-time, the destruction order becomes defined at run-time as well. So, every time you construct a local static object with non-trivial destructor, the program has to register it in some kind of linear container, which it will later use to destruct these objects in proper order.

Needless to say, the actual details depend on implementation.


It is worth adding that when it comes to static objects of "primitive" types (like int in your example) initialized with compile-time constants, the compiler is free to initialize that object at startup. You will never notice the difference. However, if you take a more complicated example with a "non-primitive" object

void go( int x ) {
static std::string s = "Hello World!";
...

then the above approach with if is what you should expect to find in the generated code even when the object is initialized with a compile-time constant.

In your case the initializer is not known at compile time, which means that the compiler has to delay the initialization and use that implicit if.

Can static variables be initialized multiple times?

count = value; is not initialization, it's assignment. Static variables can be assigned as many times as you wish.

static int count = 0; is initialization and that happens only once, no matter how many times you call demo.

Objective C - What makes a static variable initialize only once?

In computer programming, a static variable is a variable that has been allocated statically so that its lifetime or "extent" extends across the entire run of the program.

https://en.wikipedia.org/wiki/Static_variable

When are static variables initialized?

From See Java Static Variable Methods:

  • It is a variable which belongs to the class and not to object(instance)
  • Static variables are initialized only once , at the start of the execution. These variables will be initialized first, before the initialization of any instance variables
  • A single copy to be shared by all instances of the class
  • A static variable can be accessed directly by the class name and doesn’t need any object.

Instance and class (static) variables are automatically initialized to standard default values if you fail to purposely initialize them. Although local variables are not automatically initialized, you cannot compile a program that fails to either initialize a local variable or assign a value to that local variable before it is used.

What the compiler actually does is to internally produce a single class initialization routine that combines all the static variable initializers and all of the static initializer blocks of code, in the order that they appear in the class declaration. This single initialization procedure is run automatically, one time only, when the class is first loaded.

In case of inner classes, they can not have static fields

An inner class is a nested class that is not explicitly or implicitly
declared static.

...

Inner classes may not declare static initializers (§8.7) or member interfaces...

Inner classes may not declare static members, unless they are constant variables...

See JLS 8.1.3 Inner Classes and Enclosing Instances

final fields in Java can be initialized separately from their declaration place this is however can not be applicable to static final fields. See the example below.

final class Demo
{
private final int x;
private static final int z; //must be initialized here.

static
{
z = 10; //It can be initialized here.
}

public Demo(int x)
{
this.x=x; //This is possible.
//z=15; compiler-error - can not assign a value to a final variable z
}
}

This is because there is just one copy of the static variables associated with the type, rather than one associated with each instance of the type as with instance variables and if we try to initialize z of type static final within the constructor, it will attempt to reinitialize the static final type field z because the constructor is run on each instantiation of the class that must not occur to static final fields.

Why does the value of this static variable not change?

Static local variables are defined once and only once for a function, when the function is first called. Once it's defined and initialized it will never be redefined or reinitialized.

To modify the value of any variable, static or not, one must assign to it.

allocate memory to static variable only once

C and C++ standards treat initialization of objects with static storage duration differently. C++ allows both static initialization (i.e. initialization with a constant) and dynamic initialization (i.e. initialization with non-constant expression), while C allows only static initialization - i.e. with constant expressions.

The relevant portion of the C++ standard is 6.7.4:

The zero-initialization (8.5) of all local objects with static storage duration (3.7.1) is performed before any other initialization takes place. A local object of POD type (3.9) with static storage duration initialized with constant-expressions is initialized before its block is first entered. [...] Otherwise such an object is initialized the first time control passes through its declaration; such an object is considered initialized upon the completion of its initialization. (emphasis added)

C++ need additional "bookkeeping" in order to run the dynamic portion of your initializer (i.e. the call of malloc) only once. There is no similar "dynamic" provision in the C standard:

All objects with static storage duration shall be initialized (set to their initial values) before program startup.
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.

In the absence of concurrency, you can rewrite the code for use with C like this:

int foo (int num, int i) {
static int* array = NULL;
if (!array) array = malloc(sizeof(int)); // No error
printf("%d", array[i]);
return 0;
}

Now your code is responsible for the "bookkeeping": it checks array for NULL before performing the allocation.

Is there a way, in C, to ensure a function is called only once without pthread_once?

No way to leverage static variable initialization

Your attempt to leverage static variable initialization will not work. C only allows static variable to be initialized with constants, so a function call is out.

One shot call of a function at program start (or library load)

It is not clear why you want the onetime call, but if it's okay to do it at program startup, there is a GCC specific solution.
You can assign the constructor attribute to the function.

#include <stdio.h>

__attribute__((constructor))
void func()
{
puts(__func__);
}

int main () {}

This suggestion does not perform your specific ask:

I'm interested in compile-time assurance that func() is only called once from a calling function scope ...

Instead, it assures the function is called exactly once when the program starts (or when the library it is a part of is loaded).

Use a static variable as a guard

If you need to control when the function is called in the exact way initialization of a static variable local to a function is initialized, then you could use a static variable to track whether your one shot function has been called yet with its own static variable. Other answers have already described how to accomplish this, but for completeness:

void caller_of_func()
{
static bool func_already_called;
if (!func_already_called) {
func();
func_already_called = true;
}
/*...*/
}

Use a function pointer!

Another way to accomplish your goal would be to call the function through a function pointer. The initial call to the function would do the real work, and then switch the function pointer to point to a function that does nothing.

void nothing_func(int *x);
void initial_func(int *x);
void (*func)(int *x) = initial_func;

void initial_func(int *x) {
*x = 42;
puts(__func__);
func = nothing_func;
}

void nothing_func(int *x) {
puts(__func__);
}

void foo(void) {
static int x;
func(&x);
printf("%s: %d\n", __func__, x);
++x;
}

int main(void) {
foo();
foo();
}


Related Topics



Leave a reply



Submit