C Storage Classes
What are Storage Classes?
A storage class defines the scope (visibility), lifetime (how long the variable exists in memory), and default initial value of a variable. C has four storage classes:
| Storage Class | Keyword | Scope | Lifetime | Default Value |
|---|---|---|---|---|
| Automatic | auto | Local (block) | Until block ends | Garbage |
| Register | register | Local (block) | Until block ends | Garbage |
| Static | static | Local or file | Entire program | 0 |
| External | extern | Global (all files) | Entire program | 0 |
1. auto — Automatic Storage
auto is the default storage class for all local variables. You almost never write it explicitly — every local variable is auto by default. The variable is created when the block is entered and destroyed when the block exits.
#include <stdio.h>
void demo() {
auto int x = 10; // same as: int x = 10;
printf("x = %d\n", x);
// x is destroyed when demo() returns
}
int main() {
demo(); // x = 10
demo(); // x = 10 (fresh copy each call)
return 0;
}
2. register — Register Storage
register is a hint to the compiler to store the variable in a CPU register instead of RAM for faster access. Modern compilers largely ignore this hint and optimize on their own. Key restriction: you cannot take the address of a register variable (& is not allowed).
#include <stdio.h>
int main() {
register int i; // hint: store i in CPU register
int sum = 0;
for (i = 1; i <= 100; i++) {
sum += i;
}
printf("Sum 1..100 = %d\n", sum); // 5050
// ERROR: cannot take address of register variable
// printf("%p", &i); // compile error!
return 0;
}
3. static — Static Storage
static has two distinct uses:
- Static local variable — retains its value between function calls. Initialized only once.
- Static global variable / function — restricts visibility to the current file only (file-scope linkage).
#include <stdio.h>
void counter() {
static int count = 0; // initialized ONCE, persists across calls
count++;
printf("Call count: %d\n", count);
}
int main() {
counter(); // Call count: 1
counter(); // Call count: 2
counter(); // Call count: 3
return 0;
}
/*
Without static: count resets to 0 every call → always prints 1
With static: count persists → prints 1, 2, 3
*/
// file: utils.c
#include <stdio.h>
// static function — only visible within utils.c
static void helper() {
printf("Internal helper\n");
}
// static global — only visible within utils.c
static int filePrivate = 42;
void publicFunction() {
helper();
printf("filePrivate = %d\n", filePrivate);
}
// file: main.c
// extern void helper(); // ERROR — helper is static, not accessible
extern void publicFunction(); // OK — publicFunction is not static
int main() {
publicFunction();
return 0;
}
4. extern — External Storage
extern declares a variable or function that is defined in another file. It tells the compiler "this exists somewhere — the linker will find it." Use it to share global variables across multiple source files.
// globals.c — defines the global variable
int appVersion = 3; // definition (allocates memory)
void printVersion() {
printf("App version: %d\n", appVersion);
}
// main.c — uses the global variable from globals.c
#include <stdio.h>
extern int appVersion; // declaration (no memory allocated)
extern void printVersion(); // declaration
int main() {
printVersion(); // App version: 3
appVersion = 4; // modify the shared variable
printVersion(); // App version: 4
return 0;
}
// Compile: gcc globals.c main.c -o app
Quick Comparison
| Feature | auto | register | static | extern |
|---|---|---|---|---|
| Memory location | Stack | CPU register (hint) | Data segment | Data segment |
| Scope | Block | Block | Block or file | Global (all files) |
| Lifetime | Block | Block | Program | Program |
| Default value | Garbage | Garbage | 0 | 0 |
| Can take address? | Yes | No | Yes | Yes |
Ready to Level Up Your Skills?
Explore 500+ free tutorials across 20+ languages and frameworks.