Skip to content
  • Storage Classes: auto, static, extern, register · C

Storage Classes: auto, static, extern, register

LearnViaNotes @learnvianotes· 3 min read

A storage-class specifier decides where a variable lives, how long it lives (lifetime) and who can see it (linkage).

SpecifierLifetimeDefault valueScope / linkageTypical use
auto (default for locals)Until the block endsGarbageBlock, no linkageOrdinary local variables
static (local)Whole program0Block, no linkageRemember a value between calls
static (global / function)Whole program0File only (internal linkage)Hide helpers from other files
externWhole program0 (where defined)All files (external linkage)Share a global across files
registerUntil the block endsGarbageBlockHistoric hint; cannot take its address
_Thread_local (C11)Per thread0As aboveOne copy per thread

static local: state that survives calls

C
#include <stdio.h>

int next_id(void) {
    static int id = 0;      /* initialised once, before the program starts */
    int calls = 0;          /* automatic: recreated on every call */
    calls++;
    id++;
    printf("id=%d calls=%d\n", id, calls);
    return id;
}

int main(void) {
    next_id();
    next_id();
    next_id();
    return 0;
}
Output
id=1 calls=1
id=2 calls=1
id=3 calls=1

static at file level: private to the file

C — counter.c (compile-checked)
/* counter.c */
static int count = 0;                 /* invisible to other .c files */

static void log_change(void) { }      /* helper, internal linkage */

void counter_increment(void) {
    count++;
    log_change();
}

int counter_value(void) { return count; }

extern: one definition, many declarations

C
#include <stdio.h>

extern int shared;             /* declaration: "defined somewhere else" */
void bump(void);

int main(void) {
    bump();
    bump();
    printf("shared = %d\n", shared);
    return 0;
}

int shared = 100;              /* the one definition (normally in another .c file) */

void bump(void) { shared += 5; }
Output
shared = 110

register

C
int main(void) {
    register int i = 0;
    int *p = &i;            /* error: address of register variable requested */
    return *p;
}

Modern compilers ignore register for optimisation — they allocate registers far better than humans. Its only remaining effect is forbidding &. (auto in C means “automatic storage”; C23 repurposes it for type inference like C++.)

What are the differences between a static local variable and a global variable?

What does static mean for a function?

Can a static variable be initialised with a non-constant expression?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report