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
- Zero Initialization (Default):
If no initializer is provided, static local variables are initialized to
0
by default.static int x; // implicitly initialized to 0
- 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
- 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 linkage — not 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
Property | Without static | With static | Effect of static |
---|---|---|---|
Scope | Local to the block | Local to the block | ❌ Unchanged |
Duration | Automatic (created & destroyed on each function call) | Static (exists for entire program) | ✅ Changed |
Linkage | No linkage (not applicable) | No linkage (not applicable) | ❌ Not applicable |
Summary: Effects of static
on Global Variables
Property | Without static | With static | Effect of static |
---|---|---|---|
Scope | Global (accessible in file) | Global (still accessible in file) | ❌ Unchanged |
Duration | Static (entire program life) | Static (entire program life) | ❌ Unchanged |
Linkage | External (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).