Before we dive into the world of static things, we must get familiar with few things which are duration, scope and linkage.
Duration
The term duration in the context of programming particularly in C an C++, refers to the lifetime of a variable, which is the period during which the variable exists in memory. There are three main types of duration:
1️⃣ Automatic Duration
Variables with automatic duration are automatically created when the block in which they are declared is entered and destroyed when the block is exited. Most local variables have automatic duration.
Example:
#include <stdio.h>
void func() {
int autoVar = 10; // autoVar has automatic duration
printf("autoVar: %d\n", autoVar);
}
int main() {
func();
// autoVar is not accessible here and no longer exists
return 0;
}
2️⃣ Static Duration
Variables with static duration exist for the entire lifetime of the program. They are initialized once and retain their value between function calls. This applies to global variables, static local variables, and static members of a class in C++.
Example:
// Global Variable
#include <stdio.h>
int globalVar = 5; // globalVar has static duration
void func() {
printf("globalVar: %d\n", globalVar);
}
int main() {
func();
return 0;
}
// Static Local Variable
#include <stdio.h>
void func() {
static int staticVar = 0; // staticVar has static duration
staticVar++;
printf("staticVar: %d\n", staticVar);
}
int main() {
func(); // Output: staticVar: 1
func(); // Output: staticVar: 2
func(); // Output: staticVar: 3
return 0;
}
// Static Class Member (C++)
#include <iostream>
using namespace std;
class MyClass {
public:
static int staticVar; // Declaration of static member variable
void increment() {
staticVar++;
}
void show() {
cout << "staticVar: " << staticVar << endl;
}
};
int MyClass::staticVar = 0; // Definition of static member variable
int main() {
MyClass obj1, obj2;
obj1.increment();
obj2.increment();
obj1.show(); // Output: staticVar: 2
return 0;
}
Scope
Scope refers to the region of the program where a particular variable or function is accessible.
1️⃣ Block Scope | Local Scope
Variables declared inside a block (e.g., within curly braces {}
) have block scope. They are only accessible within that block.
Example:
#include <stdio.h>
void func() {
int localVar = 42; // localVar has block scope
printf("localVar inside func: %d\n", localVar);
}
int main() {
func();
// localVar is not accessible here
// printf("%d\n", localVar); // This would cause a compilation error
return 0;
}
2️⃣ File Scope | Global Scope
Variables and functions declared outside of any function have file scope. They are accessible from the point of declaration to the end of the file.
Example:
#include <stdio.h>
int globalVar = 100; // globalVar has file scope
void func() {
printf("globalVar inside func: %d\n", globalVar);
}
int main() {
func();
printf("globalVar inside main: %d\n", globalVar);
return 0;
}
3️⃣ Function Scope
Labels used in goto
statements have function scope. They are only accessible within the function they are declared in.
Example:
#include <stdio.h>
void func() {
goto label;
label:
printf("This is a label.\n");
}
int main() {
func();
return 0;
}
4️⃣ Class Scope (C++ Only)
Members of a class (variables and functions) have class scope. They are accessible within the class and through objects or pointers to objects of the class.
Example:
#include <iostream>
using namespace std;
class MyClass {
public:
int memberVar;
void memberFunc() {
cout << "memberVar inside memberFunc: " << memberVar << endl;
}
};
int main() {
MyClass obj;
obj.memberVar = 123;
obj.memberFunc();
return 0;
}
5️⃣ Namespace Scope (C++ Only)
Variables, functions, and classes declared inside a namespace have namespace scope. They are accessible within the namespace and can be accessed outside the namespace using the scope resolution operator ::
.
Example:
#include <iostream>
using namespace std;
namespace MyNamespace {
int var = 10;
void func() {
cout << "var inside MyNamespace::func: " << var << endl;
}
}
int main() {
MyNamespace::func();
cout << "var accessed through MyNamespace: " << MyNamespace::var << endl;
return 0;
}
Linkage
Linkage refers to the visibility of symbols (variables and functions) across different translation units (source files). In simple, it determines whether a variable can be accessed (or linked) in another file. Basically there are three types of linkage.
1️⃣ External Linkage
A symbol with external linkage is visible to and can be referenced from other translation units. These can be accessed from other files using the extern
keyword. By default, global variables and functions have external linkage.
Example:
// file1.c
int globalVar = 42; // External linkage by default
void func() { // External linkage by default
// function code
}
// file2.c
extern int globalVar; // Declaration to access the global variable from file1.c
extern void func(); // Declaration to access the function from file1.c
void anotherFunc() {
globalVar = 100;
func();
}
2️⃣ Internal Linkage
A symbol with internal linkage is only visible within the same translation unit. This is achieved using the static
keyword.
Example:
// file1.c
static int internalVar = 42; // Internal linkage
static void internalFunc() { // Internal linkage
// function code
}
// file2.c
int internalVar = 100; // This is a different variable than internalVar in file1.c
void internalFunc() { // This is a different function than internalFunc in file1.c
// function code
}
3️⃣ No Linkage
A symbol with no linkage is only visible within the scope in which it is declared. This typically applies to local variables and parameters of functions.
Example:
void func() {
int localVar = 42; // No linkage
// localVar is only visible within func
}
void anotherFunc() {
int localVar = 100; // No linkage
// This localVar is different from the one in func
}