Skip to content
FollowtheDamnCode

Scope and Storage Classes

Where a variable can be seen, and how long it lives.

7 minute read

Big idea

Scope is where a name can be used. Storage is how long the variable lives. Most variables live inside { } and vanish at the } — static and globals live for the whole program.

Local variables

A variable declared inside a function (or any { } block) is local: only code inside that block can see it, and it's created fresh each time the block runs.

void f(void) {
    int count = 0;      // local to f
}
// count doesn't exist out here

Two functions can each have their own count — they're different variables that happen to share a name.

Global variables

A variable declared outside every function is global: every function below it can see it, and it lives as long as the program runs. If you don't initialise it, it starts at 0.

A global shared by two functions
#include <stdio.h>

int total = 0;            // global

void add(int x) {
    total += x;
}

int main(void) {
    add(5);
    add(7);
    printf("total = %d\n", total);
    return 0;
}
output
total = 12

Run and edit it in the app.

Handy, but every function can change a global, so when it has the wrong value, any line in the program could be the culprit. Prefer parameters and return values; reach for globals rarely.

Shadowing

A local with the same name as a global hides the global inside its block:

Predict: which x is printed?
#include <stdio.h>

int x = 1;

int main(void) {
    printf("%d\n", x);
    int x = 2;
    printf("%d\n", x);
    {
        int x = 3;
        printf("%d\n", x);
    }
    printf("%d\n", x);
    return 0;
}
What does it print? Show the answer
1
2
3
2

Run and edit it in the app.

Each { } can declare its own x; the innermost one wins until its block ends. Legal — but confusing. Give things different names.

Watch the names get hidden

static: a local that remembers

Put static on a local variable and it's created once, keeps its value between calls, and is still only visible inside its function:

Take static away and every call prints 1 — try it:

Fix the bug: every ticket gets number 1
#include <stdio.h>

int next_ticket(void) {
    int number = 0;
    number++;
    return number;
}

int main(void) {
    for (int i = 0; i < 3; i++) {
        printf("Ticket %d\n", next_ticket());
    }
    return 0;
}
output
Ticket 1
Ticket 2
Ticket 3

Run and edit it in the app.

The storage-class keywords

KeywordOn a localOn a global or function
(none)automatic: made each time the block runs, gone at its }visible to other files of the program
staticlives for the whole program, keeps its valueprivate to this file
extern—"this exists, defined in another file" — a declaration, not a new variable
registera hint to keep it in a CPU register; you can't take its &—
  • extern matters once a program is split over several files — see Multi-File Programs.
  • register is a leftover from old compilers; modern ones decide better than we can. You'll read it in old code, but there's no need to write it.

void f(void) { static int n = 10; n += 5; printf("%d ", n); } — what do three calls to f() print?

Common mistake

Returning the address of an ordinary local:

int *bad(void) {
    int x = 42;
    return &x;      // ✗ x dies when bad() returns
}

The caller gets a dangling pointer to memory that's already been reused. Return the value, use static, or use malloc.

Think of it like

A local variable is a whiteboard in a meeting room — wiped when the meeting ends. A static local is a notebook kept in that room's drawer: only people in the room use it, but it's still there next meeting. A global is the noticeboard in the corridor — everyone can read it, and anyone can scribble on it.

Key terms

  • Scope — The part of the code where a name is visible.
  • Lifetime — How long a variable exists while the program runs.
  • Local (automatic) variable — Declared in a block; lives until the block ends.
  • Global variable — Declared outside functions; lives for the whole program.
  • static — On a local: keeps its value between calls. On a global or function: private to its file.
  • Shadowing — An inner variable hiding an outer one with the same name.

Check yourself

When does an ordinary local variable stop existing?

What does static do to a local variable?

What does extern int count; mean?