Nearby lessons
111 of 124C - static Storage Class
static is the most useful — and most confusing — storage class in C, because it does two different jobs. Inside a function it makes a variable survive between calls; at file scope it hides a name from other files.
The Two Meanings
static answers "how long does it live?" — the whole program. At file scope, lifetime is already the whole program, so it answers a different question: "who can see it?" — only this file.| Written | Changes | Effect |
|---|---|---|
| Inside a function | Lifetime | Survives between calls |
| On a file-scope variable | Linkage | Private to this file |
| On a function | Linkage | Callable only from this file |
A Static Local Remembers
The classic use — a counter that keeps its value without exposing a global:
The Initialiser Runs Once
static int id = 0; does not reset id on every call. Reading the line as an ordinary assignment is the single most common misunderstanding of static. The initialisation happens once, before main starts — the line is effectively skipped on every call after the first.Zero by Default
A static variable with no initialiser is zeroed. Unlike an automatic variable, this is guaranteed:
The Initialiser Must Be Constant
Because the value is set before the program runs, it cannot depend on anything computed at run time:
Scope Is Unchanged
A static local is still invisible outside its function. Only the lifetime changed — this is the difference between static and a global:
static at File Scope
A file-scope variable is shared across the whole program by default. Adding static makes it private, which is how C achieves encapsulation:
static Functions
Marking a helper static keeps it out of other files' reach, prevents name clashes at link time, and lets the compiler optimise it more aggressively:
A Practical Use — One-Time Setup
A static flag makes a function initialise itself exactly once, however many times it is called:
Where static Goes Wrong
static, and also its danger. Recursive calls all share the same variable rather than getting their own, so a depth counter never unwinds. Two threads calling the same function race on it. And a function returning a pointer to a static buffer hands every caller the same memory — the second call silently overwrites the first result.Common Mistakes
- Expecting the initialiser to run every call — it runs once, before
main. - Using a non-constant initialiser — a compile error; initialise lazily with a flag.
- Using a static counter in a recursive function — it is shared, so it never unwinds.
- Returning a pointer to a static local buffer — the next call overwrites the previous caller's data.
- Using statics in multithreaded code — one shared copy means a data race.
- Confusing the two meanings — lifetime inside a function, linkage at file scope.
- Using
staticto make a global "safer" — it hides it from other files but not from the rest of this one.
static on functions and file-scope variables by default; static on locals only when you have a reason." The first two are pure benefit — they shrink the public surface of a file. The third introduces hidden state, and hidden state is where the awkward bugs live.- Inside a function, static changes lifetime: the value survives between calls.
- At file scope, static changes linkage: the name is private to that file.
- A static variable is initialised once, before main runs, and defaults to zero.
- Its initialiser must be a constant expression.
- One shared copy makes it unsafe for recursion and threads.