Skip to content
Laviyx Learn

Try

C course menu

Scope and Storage Classes in C: local, global, static, extern and register

Understand scope and lifetime in C: block scope and local variables, global variables and their risks, static local variables that keep their value, static functions and globals with internal linkage, extern declarations, and automatic versus static storage.

Beginner8 min readUpdated
On this page

Two questions apply to every variable in C:

  • Scope: where in the code can the name be used?
  • Lifetime (storage duration): how long does the variable exist in memory?

Local variables#

Variables declared inside a function or block are local. They can only be used inside that block, and they are created each time the block runs and destroyed when it ends (automatic storage):

C
#include <stdio.h>

void counter(void) {
    int count = 0;         /* created fresh on every call */
    count++;
    printf("count = %d\n", count);
}

int main(void) {
    counter();
    counter();
    counter();
    return 0;
}
Output
count = 1
count = 1
count = 1

static local variables#

Adding static to a local variable gives it static storage: it is created once, keeps its value between calls, and is initialised (to zero if no value is given) before the program starts. Its scope is still local:

C
#include <stdio.h>

int next_ticket(void) {
    static int ticket = 100;   /* initialised once */
    ticket++;
    return ticket;
}

int main(void) {
    printf("%d\n", next_ticket());
    printf("%d\n", next_ticket());
    printf("%d\n", next_ticket());
    return 0;
}
Output
101
102
103

Global variables#

Variables declared outside all functions are global: visible from their declaration to the end of the file (and to other files that declare them extern), and alive for the whole program. Unlike locals, they start at zero:

C
#include <stdio.h>

int visits;            /* global: automatically 0 */

void record_visit(void) {
    visits++;
}

int main(void) {
    record_visit();
    record_visit();
    printf("visits = %d\n", visits);
    return 0;
}
Output
visits = 2

Globals are convenient but risky: any function can change them, which makes bugs hard to trace, and they make code harder to reuse and test. Prefer passing values as parameters. Keep globals for genuinely program-wide state, and make them static when only one file needs them.

Shadowing#

A local variable with the same name as an outer one hides it within its block:

C
#include <stdio.h>

int level = 1;

int main(void) {
    int level = 2;
    {
        int level = 3;
        printf("%d\n", level);
    }
    printf("%d\n", level);
    return 0;
}
Output
3
2

Shadowing is legal but confusing; -Wshadow makes GCC warn about it.

static at file level and extern#

At file level, static means something different: internal linkage. A static global variable or function is private to its .c file, so other files cannot see it, and its name cannot clash with names elsewhere. Without static, a global function or variable has external linkage and can be used from other files.

extern declares a variable that is defined in another file:

config.c (C)
int max_users = 100;            /* definition: external linkage */
static int secret_seed = 42;    /* private to config.c */
main.c (C)
extern int max_users;           /* declaration: defined elsewhere */

This is explored in Header Files and Multi-file Programs.

Summary#

DeclaredKeywordScopeLifetimeDefault value
Inside a block(none)The blockEach time the block runsGarbage (uninitialised)
Inside a blockstaticThe blockThe whole program0
Outside functions(none)The file, plus other files via externThe whole program0
Outside functionsstaticThis file onlyThe whole program0

The register keyword (a hint to keep a variable in a CPU register) still exists, but modern compilers ignore it and decide for themselves.

Practice#

Practice exercise

Write a function int average_so_far(int value) that keeps a running total and count in static variables and returns the integer average of all values passed so far. Call it with 10, 20 and 60.

Show solution
C
#include <stdio.h>

int average_so_far(int value) {
    static int total = 0;
    static int count = 0;
    total += value;
    count++;
    return total / count;
}

int main(void) {
    printf("%d\n", average_so_far(10));
    printf("%d\n", average_so_far(20));
    printf("%d\n", average_so_far(60));
    return 0;
}
Output
10
15
30

Key takeaway#

Finished this lesson?