C Storage Classes
Every variable in a C program has more than just a data type — it also has a storage class. A storage class defines three things about a variable: where it is stored in memory, how long it lives during program execution, and where in the code it can be accessed.
C has four storage classes: auto, extern, static, and register.
The Three Properties of a Storage Class
| Property | What It Means |
|---|---|
| Storage Location | Where the variable lives in memory (stack, heap, data segment, CPU register) |
| Lifetime | How long the variable exists — until the block ends, or until the program ends |
| Scope | Where in the code the variable is visible and accessible |
1. auto — Automatic Storage Class
The auto keyword is the default storage class for all local variables. When you declare a variable inside a function without any storage class keyword, it is automatically auto.
- Storage: Stack
- Lifetime: Exists only while the block (function or loop) it is declared in is executing
- Scope: Only visible inside the block it is declared in
- Default Value: Garbage (undefined) — always initialize before use
#include <stdio.h>
void showAuto()
{
auto int count = 0; // 'auto' is optional here
count++;
printf("count = %d\n", count);
}
int main()
{
showAuto(); // count = 1
showAuto(); // count = 1 (reset each call — not remembered)
showAuto(); // count = 1
return 0;
}
The variable count is created fresh every time showAuto() is called and destroyed when the function returns.
2. extern — External Storage Class
The extern keyword declares that a variable is defined somewhere else in the program (in another file or outside the current function). It does not create a new variable — it references an existing one.
- Storage: Data segment (global memory)
- Lifetime: Entire program execution
- Scope: Can be accessed from any file in the program (global visibility)
- Default Value: Zero for numbers, NULL for pointers
// file1.c
int globalScore = 100; // defined here
// file2.c
extern int globalScore; // declared here — uses the variable from file1.c
void printScore() {
printf("Score: %d\n", globalScore); // Output: 100
}
extern in a single file
#include <stdio.h>
int total = 500; // global variable
void showTotal()
{
extern int total; // refers to the global variable above
printf("Total: %d\n", total); // Output: 500
}
int main()
{
showTotal();
return 0;
}
3. static — Static Storage Class
The static keyword gives a variable a permanent memory location. A static local variable keeps its value between function calls — it is not reset every time the function runs.
- Storage: Data segment (permanent memory)
- Lifetime: Entire program execution
- Scope (local static): Only inside the function/block where declared
- Scope (global static): Only inside the file where declared (cannot be accessed from other files)
- Default Value: Zero
Static local variable — remembers its value
#include <stdio.h>
void counter()
{
static int count = 0; // initialized only ONCE
count++;
printf("count = %d\n", count);
}
int main()
{
counter(); // count = 1
counter(); // count = 2
counter(); // count = 3
return 0;
}
Unlike auto, the static count variable retains its value between calls. It is initialized to 0 only once, the very first time the function runs.
Static vs Auto — Visual Comparison
Function call 1:
auto count: [created] 0 → 1 → [destroyed]
static count: [created] 0 → 1 → [stays in memory]
Function call 2:
auto count: [created] 0 → 1 → [destroyed]
static count: [still in memory] 1 → 2 → [stays]
Function call 3:
auto count: [created] 0 → 1 → [destroyed]
static count: [still in memory] 2 → 3 → [stays]
Static global variable — restricted to file
// In file1.c
static int secretValue = 42; // only accessible in file1.c
// In file2.c
extern int secretValue; // ERROR — cannot access, it's static in file1.c
4. register — Register Storage Class
The register keyword is a hint to the compiler to store the variable in a CPU register instead of RAM. CPU registers are the fastest storage available — accessing a register is much faster than accessing RAM.
- Storage: CPU register (if available; otherwise treated like auto)
- Lifetime: Same as auto — exists only while the block runs
- Scope: Same as auto — only visible inside the block
- Limitation: You cannot take the address of a register variable with
&
#include <stdio.h>
int main()
{
register int i; // suggest storing i in a CPU register
for (i = 0; i < 1000000; i++)
{
// very fast loop — i accessed from register, not RAM
}
printf("Done. i = %d\n", i);
return 0;
}
Note: Modern compilers automatically optimize variable placement. The register keyword is largely ignored in modern C but still valid syntax.
Storage Classes Comparison Table
| Storage Class | Location | Lifetime | Scope | Default Value |
|---|---|---|---|---|
auto | Stack | Block duration | Local block only | Garbage |
extern | Data segment | Full program | Multiple files | 0 / NULL |
static | Data segment | Full program | Local block or single file | 0 / NULL |
register | CPU register | Block duration | Local block only | Garbage |
Memory Layout and Storage Classes
Memory Layout of a C Program:
+---------------------------+
| Stack | ← auto variables (local variables)
| (grows downward) |
+---------------------------+
| Heap | ← dynamically allocated memory (malloc)
| (grows upward) |
+---------------------------+
| BSS Segment | ← uninitialized static & extern variables (auto = 0)
+---------------------------+
| Data Segment | ← initialized static & extern variables
+---------------------------+
| Code Segment (Text) | ← program instructions
+---------------------------+
register variables: CPU registers (fastest, outside main memory)
Practical Example: Counting Function Calls
#include <stdio.h>
void greet()
{
static int callCount = 0;
callCount++;
printf("Greet called %d time(s)\n", callCount);
}
int main()
{
greet(); // Greet called 1 time(s)
greet(); // Greet called 2 time(s)
greet(); // Greet called 3 time(s)
return 0;
}
Summary
Storage classes in C define how and where variables are stored, how long they live, and where they can be accessed. The auto class is the default for local variables — they live on the stack and are destroyed when the block exits. The extern class declares a variable defined elsewhere, giving it global reach across files. The static class makes a variable persistent across function calls or restricts a global variable to a single file. The register class hints to the compiler to use a CPU register for speed. Choosing the right storage class leads to cleaner, more efficient, and more maintainable C programs.
