Functions
Scope & Storage Classes
Where variables live and how long they last: local, global and block scope, plus the auto, static, extern and register storage classes.
Every variable has a scope (where in the code its name can be used) and a lifetime (how long its memory exists). A storage class keyword controls both.
Local, global and block scope
#include <stdio.h>
int counter = 0; // global: visible in every function below
void visit(void) {
counter++; // uses the global
int local = 10; // local: exists only during this call
printf("visit: counter = %d, local = %d\n", counter, local);
}
int main(void) {
visit();
visit();
int x = 1;
{
int x = 2; // block scope: this x hides the outer x
printf("inner x = %d\n", x);
}
printf("outer x = %d\n", x);
return 0;
}visit: counter = 1, local = 10 visit: counter = 2, local = 10 inner x = 2 outer x = 1
When an inner variable has the same name as an outer one, the inner one shadows it inside its block.
The four storage classes
| Storage class | Where stored | Default value | Scope | Lifetime |
|---|---|---|---|---|
auto |
stack | garbage | block | until the block ends |
register |
CPU register (a hint) | garbage | block | until the block ends |
static |
data segment | 0 | block (or file) | the whole program |
extern |
data segment | 0 | global | the whole program |
auto
Every local variable is auto by default, so you never need to write the keyword.
static
A static local variable is created once and keeps its value between calls:
#include <stdio.h>
void countCalls(void) {
static int calls = 0; // initialised only once
int normal = 0; // re-created on every call
calls++;
normal++;
printf("calls = %d, normal = %d\n", calls, normal);
}
int main(void) {
countCalls();
countCalls();
countCalls();
return 0;
}calls = 1, normal = 1 calls = 2, normal = 1 calls = 3, normal = 1
A static global variable or function is visible only inside its own .c file — a simple way to hide helpers from other files.
extern
extern declares a global variable that is defined in another file (or later in this one). It does not create new memory:
// file1.c
int total = 50; // definition: memory is created here
// file2.c
extern int total; // declaration: "total exists somewhere else"
void show(void) { printf("%d\n", total); }register
register int i; asks the compiler to keep i in a CPU register for speed. Modern compilers ignore the hint and decide for themselves. You cannot take the address (&i) of a register variable.
Test yourself
4 questions · pick an answer to check it instantly
- 1
What is the default initial value of a
static intvariable?Static and global variables are zero-initialised. Localautovariables hold garbage. - 2
A
staticlocal variable keeps its value...It is stored in the data segment, not on the stack, so it outlives each call. - 3
What does
extern int count;do?externis a declaration, not a definition. - 4
Which storage class forbids taking the variable's address with
&?A register variable may not live in memory, so it has no address.