storage duration (static, extern, automatic)
Every variable's storage exists for some span of time, and C gives you a few keywords to choose that span and a couple of related properties. Think of it as deciding the rental term for a value's memory: rent it just for the duration of one phone call (automatic), or keep the lease for the whole life of the program (static). The keywords static, extern, and the default automatic case control this.
Automatic storage is the default for variables declared inside a block: their storage is allocated when control enters the block (typically on the call stack) and freed when it leaves, so each call gets a fresh copy. static gives static storage duration: the variable exists for the entire program run and keeps its value between entries; written inside a function it is a persistent counter that is still only visible there, and written at file scope it ALSO restricts visibility to that single file (internal linkage). extern is different in kind — it does not create storage but declares that a variable (or function) with external linkage is defined in another translation unit, letting separate files share one object. There is also register, a now-obsolete hint that a variable be kept in a CPU register.
Why this matters: these keywords are how you control both how long data lives and which files can see it. A common source of confusion is that the single word static does two unrelated jobs depending on context — 'lives for the whole program' inside a function, and 'visible only in this file' at file scope. Knowing which one you are invoking is essential to organizing a multi-file program cleanly.
/* file a.c */ int shared = 0; /* external: other files can see it */ static int hidden = 0; /* file scope: only a.c sees it */ void f(void) { int once; /* automatic: new each call */ static int total = 0; /* persists across calls */ } /* file b.c */ extern int shared; /* declare a.c's shared to use it */
static at file scope hides a name; static inside a function makes it persist. extern in b.c borrows a.c's variable rather than creating a new one.
The keyword static means two different things by context: 'lives for the whole program' inside a function, but 'visible only in this file' (internal linkage) at file scope. extern declares, it does not define — it never allocates storage.