Storage Classes
What is a storage class?
When you declare a variable in C, the compiler needs to know more than just its type. It needs to know where the variable can be used, how long it should stay alive in memory, and what value it starts with if you do not set one. A storage class answers exactly these three questions.
So every variable has three properties tied to its storage class:
- Scope — the region of code where the variable is visible.
- Lifetime — how long the variable exists in memory.
- Default value — what it holds if left uninitialised.
C gives you four storage-class keywords to set these: auto, register, static and extern.
The four storage classes at a glance
| Keyword | In one line |
|---|---|
auto | The automatic default for every local variable. |
register | A hint to keep the variable in a fast CPU register. |
static | Keeps its value between function calls; also hides globals in a file. |
extern | Refers to a global variable defined in another file. |
Now let's look at each one with a working example.
auto — the default local
Any variable you declare inside a function is automatically auto. Writing the keyword is optional and adds nothing — which is why you almost never see it in real code.
#include <stdio.h>
int main() {
auto int x = 10; // same as: int x = 10;
int y = 20; // y is also auto by default
printf("x = %d, y = %d\n", x, y);
return 0;
}x = 10, y = 20
An auto variable is created when the block starts and destroyed when the block ends. Its default value is garbage — always initialise it.
register — a speed hint
The register keyword requests that a variable be kept in a CPU register instead of RAM, which is faster to access. It is only a request: the compiler may ignore it. A common use was tight loop counters.
#include <stdio.h>
int main() {
register int i;
for (i = 1; i <= 3; i++)
printf("%d ", i);
return 0;
}1 2 3
You cannot take the address of a register variable — &i is an error. Modern compilers optimise so well that register is effectively obsolete today.
static — remembers its value
This is the most useful storage class. A static local variable is initialised only once and keeps its value across function calls, because its lifetime is the whole program — not a single call.
#include <stdio.h>
void counter() {
static int count = 0; // set once, survives calls
count++;
printf("Call number: %d\n", count);
}
int main() {
counter();
counter();
counter();
return 0;
}Call number: 1
Call number: 2
Call number: 3
If count were an ordinary local variable, it would reset to 0 on every call and always print 1. Being static is what lets it count.
A global variable marked static becomes private to its file — other files cannot access it with extern. This is a clean way to hide internal helpers.
extern — shared across files
Large programs are split across several .c files. When one file needs a global variable that is defined in another file, it uses extern to say "this exists elsewhere, trust me."
#include <stdio.h>
int score = 100; // actual definition
void show(void); // from file2.c
int main() {
show();
return 0;
}#include <stdio.h>
extern int score; // declared here, defined in file1.c
void show(void) {
printf("Score = %d\n", score);
}Score = 100
extern only declares — it never allocates memory. Exactly one file must actually define the variable (here, file1.c).
Scope, lifetime & default value
| Storage class | Scope | Lifetime | Default value |
|---|---|---|---|
| auto | Local (block) | Until block ends | Garbage |
| register | Local (block) | Until block ends | Garbage |
| static | Local or file | Whole program | 0 |
| extern | Global (all files) | Whole program | 0 |
Common mistakes
- Expecting an ordinary local variable to remember its value between calls — you need
staticfor that. - Trying to take the address of a register variable with
&. - Using
externand also initialising the variable in the same line in every file — only one file should define it. - Assuming
autovariables start at 0 — they hold garbage until initialised.
Write a function int nextId() that returns 1, 2, 3, … on successive calls using a static counter. Then try removing static and observe how the output changes.
Summary
- A storage class sets a variable's scope, lifetime and default value.
autois the default for locals — you never need to write it.registerhints at CPU-register storage; it is obsolete today.statickeeps a local's value across calls, and hides globals inside a file.externlets one file use a global defined in another file.
Frequently Asked Questions
What do storage classes actually control in C?
Is auto ever needed in modern C?
auto by default, so writing the keyword adds nothing. In C++11 and later auto means something completely different (type deduction), so in practice you simply never type auto in C.Why does a static local variable keep its value between calls?
What is the difference between static and extern?
extern tells the compiler a global variable is defined in another file so this file can use it. static at file level does the reverse — it hides a global variable so other files cannot see it.Does register actually make my program faster?
register is only a suggestion to keep a variable in a CPU register, and modern compilers already make far better decisions than the hint. You also cannot take the address of a register variable with &. In real code it is effectively obsolete.