Storage Classes (auto / static / extern / register)
Every variable in C has a storage class, which controls two things: where it lives in memory and how long it lives (its storage duration), and which parts of the program can see it (its linkage). C has four storage-class keywords: auto, static, extern, and register.
auto — the default, rarely written explicitly
Every local variable you've written so far has actually been auto by default — it's the automatic, implicit storage class for variables declared inside a function or block, so nobody writes it out:
void greet(void) {
auto int count = 0; /* legal, but nobody writes "auto" -- it's implied */
int total = 0; /* identical meaning -- auto is the default */
}static — persists across function calls
A static local variable is initialized only once and then keeps its value between calls to the function, instead of being recreated every time:
#include <stdio.h>
int next_id(void) {
static int counter = 0; /* initialized once, ever */
counter++;
return counter;
}
int main(void) {
printf("%d\n", next_id()); /* 1 */
printf("%d\n", next_id()); /* 2 */
printf("%d\n", next_id()); /* 3 */
return 0;
}1 2 3
Compare that with an ordinary auto local, which resets to its initializer every call:
int not_counting(void) {
int counter = 0; /* recreated fresh every call */
counter++;
return counter;
}
/* not_counting() always returns 1, no matter how many times it's called */static has a second, unrelated-looking use: at file scope (outside any function), it gives a global variable or function internal linkage — meaning it's only visible within that source file, and other .c files in the same program can't reference it even with extern:
static int internal_cache_size = 128; /* only visible in this .c file */
static void helper(void) { /* only callable from this .c file */
/* ... */
}extern — refers to a definition elsewhere
extern tells the compiler "this variable or function exists, but it's defined somewhere else — trust me and don't allocate storage for it here." It's how you share a global variable or function across multiple source files:
config.c
int app_version = 3; /* the one real definition, allocates storage */
main.c
#include <stdio.h>
extern int app_version; /* declaration only -- refers to config.c's variable */
int main(void) {
printf("Version: %d\n", app_version);
return 0;
}register — a hint to the compiler
register suggests that a variable will be used heavily and asks the compiler to keep it in a CPU register instead of ordinary memory, for faster access. A variable declared register cannot have its address taken with &.
int sum_to(int n) {
register int i;
register int total = 0;
for (i = 1; i <= n; i++) {
total += i;
}
return total;
}Summary
Keyword | Typical use | Effect |
|---|---|---|
auto | Local variables (default, rarely written) | Automatic storage duration -- recreated each call/block entry |
static | Local variable that must persist, or file-scope internal linkage | Retains value across calls; or restricts visibility to one file |
extern | Sharing a global across multiple .c files | Refers to a definition that exists elsewhere -- no storage allocated here |
register | A rarely-needed optimization hint (mostly historical) | Suggests keeping the variable in a CPU register; compilers may ignore it |