CLOSE

The term static in C++ can be perplexing due to its diverse meanings in different contexts.

In an earlier discussion, we learned that global variables have static duration, meaning they are created at the start of the program and destroyed at the end. Similarly, the static keyword can be applied to local variables to modify their lifetime and storage class.

Static on Local Variables

By default, local variables have automatic duration, meaning:

  • They are created when the function or block is entered, and
  • They are destroyed when the block is exited.

However, when a local variable is declared with the static keyword, its duration changes from automatic to static. This means:

  • It is created once at the start of the program, and
  • It is destroyed only when the program ends.

As a result, a static local variable retains its value across multiple function calls, unlike regular local variables.

Example: Local Variable with Automatic Duration (Default):

#include <iostream>

void incrementAndPrint() {
    int value{ 1 }; // automatic duration by default
    ++value;
    std::cout << value << '\n';
} // value is destroyed here

int main() {
    incrementAndPrint();
    incrementAndPrint();
    incrementAndPrint();
    return 0;
}
// Output

2
2
2

Explanation:

Each time incrementAndPrint() is called:

  • A new value is created and initialized to 1.
  • It is incremented to 2 and printed.
  • The variable is destroyed at the end of the function.

Since the variable is recreated each time, the output is always 2.

Example: Location Variable with Static Duration (Using static):

#include <iostream>

void incrementAndPrint() {
    static int s_value{ 1 }; // static duration via static keyword.
    ++s_value;
    std::cout << s_value << '\n';
} // s_value is not destroyed here

int main() {
    incrementAndPrint();
    incrementAndPrint();
    incrementAndPrint();
    return 0;
}
// Output

2
3
4

Explanation:

  • s_value is a static local variable.
  • It is initialized only once, at program start, with the value 1.
  • Its value persists across function calls.
  • The variable is not destroyed when the function ends.

Thus, the value accumulates: 2, then 3, then 4.

Initialization Rules for Static Local Variables

  1. Zero Initialization (Default):
    • If no initializer is provided, static local variables are initialized to 0 by default.

      static int x; // implicitly initialized to 0
      
  2. Compile-time (constexpr) Initialization:
    • If a static local variable has a constexpr initializer (like a literal value), it is initialized at program startup.

      static int y { 5 }; // initialized at program start
      
  3. f the initializer is non-constant, the variable is:
    • Zero-initialized at program start, then
    • Initialized on the first function call (only once).

      static int z = someRuntimeFunction(); // runtime initialization

static on Global Variables

When the static keyword is applied to a global variable (i.e., a variable declared outside any function), it changes its linkagenot its duration or scope.

By default, global variables:

  • Have global scope (accessible from the point of definition onward within the file).
  • Have external linkage (can be accessed from other files using extern).
  • Have static storage duration (exist for the entire duration of the program).

When static is applied to a global variable:

  • It limits the linkage to internal, meaning the variable becomes private to the file it’s declared in.
  • This prevents other files from accessing or modifying the variable, even if they use extern.

Example: External Linkage (Default Global Variable)

file1.cpp

#include <iostream>

int globalCounter = 0;  // External linkage by default

void incrementCounter() {
    ++globalCounter;
}

file2.cpp

#include <iostream>

extern int globalCounter;  // Declaration from another file

void printCounter() {
    std::cout << "Counter: " << globalCounter << '\n';
}

This works fine.file2.cpp accesses globalCounter from file1.cpp because the variable has external linkage by default.

Example: Internal Linkage (Using static)

file1.cpp

#include <iostream>

static int localCounter = 0;  // Internal linkage (limited to this file)

void incrementLocalCounter() {
    ++localCounter;
}

file2.cpp

#include <iostream>

extern int localCounter;  // ❌ Error: 'localCounter' has internal linkage

void printLocalCounter() {
    std::cout << "Counter: " << localCounter << '\n';  // Compilation error
}

Compilation error. Since localCounter is declared static in file1.cpp, it cannot be accessed in file2.cpp.

Summary: Effects of static on Local Variables

PropertyWithout staticWith staticEffect of static
ScopeLocal to the blockLocal to the block❌ Unchanged
DurationAutomatic (created & destroyed on each function call)Static (exists for entire program)✅ Changed
LinkageNo linkage (not applicable)No linkage (not applicable)❌ Not applicable

Summary: Effects of static on Global Variables

PropertyWithout staticWith staticEffect of static
ScopeGlobal (accessible in file)Global (still accessible in file)❌ Unchanged
DurationStatic (entire program life)Static (entire program life)❌ Unchanged
LinkageExternal (accessible across files)Internal (restricted to this file)✅ Changed

Conclusion:

In C/C++, the effect of the static keyword depends on where it's used:

When used with local variables, static changes the duration from automatic (per function call) to static (entire program lifetime).


When used with global variables, static changes the linkage from external (visible across files) to internal (restricted to the current file).