Nearby lessons

109 of 124

C - Storage Classes

A storage class tells the compiler where a variable lives, how long it lives, and who can see it. Learn the four keywords — auto, register, static and extern — and the three properties they control.

The Four Storage Classes

One table covers the whole topic. Everything that follows is detail:

KeywordStored inLifetimeDefault valueScope
autoStackThe blockGarbageThe block
registerRegister (a hint)The blockGarbageThe block
staticData segmentWhole programZeroBlock or file
externData segmentWhole programZeroEvery file
Example01
CCode Cell
1#include <stdio.h>
2 
3int globalVar = 10; /* extern by default */
4 
5void demo(void)
6{
7 auto int a = 1; /* 'auto' is the default anyway */
8 register int r = 2; /* a hint to keep in a register */
9 static int s = 3; /* survives between calls */
10 
11 printf("a=%d r=%d s=%d global=%d\n", a, r, s, globalVar);
12 a++; s++; /* a resets next call, s does not */
13}
14 
15int main()
16{
17 demo();
18 demo();
19 demo();
20 return 0;
21}
Output
a=1 r=2 s=3 global=10
a=1 r=2 s=4 global=10
a=1 r=2 s=5 global=10

Three Separate Questions

In simple words: storage classes answer three independent questions. Scope — from where in the source can I write its name? Lifetime — for how long does its memory exist? Linkage — can another .c file reach it? Mixing these three up is the reason storage classes feel confusing.
Example02
CCode Cell
1#include <stdio.h>
2 
3void counter(void)
4{
5 static int calls = 0; /* scope: this function
6 lifetime: the whole program
7 linkage: none */
8 int local = 0; /* scope: this function
9 lifetime: this call
10 linkage: none */
11 calls++;
12 local++;
13 printf("call %d, local %d\n", calls, local);
14}
15 
16int main()
17{
18 counter();
19 counter();
20 counter();
21 
22 /* printf("%d", calls); ERROR: out of scope here,
23 even though the memory still exists */
24 return 0;
25}
Output
call 1, local 1
call 2, local 2
call 3, local 3

Scope — Where the Name Is Visible

Scope is decided by where you write the declaration, not by the storage class:

Example03
CCode Cell
1#include <stdio.h>
2 
3int fileScope = 100; /* visible from here to end of file */
4 
5int main()
6{
7 int functionScope = 200; /* visible in main */
8 
9 {
10 int blockScope = 300; /* visible only in these braces */
11 printf("Inside block : %d %d %d\n",
12 fileScope, functionScope, blockScope);
13 }
14 
15 /* printf("%d", blockScope); ERROR: out of scope */
16 printf("Outside block: %d %d\n", fileScope, functionScope);
17 return 0;
18}
Output
Inside block : 100 200 300
Outside block: 100 200

Lifetime — How Long the Memory Exists

An automatic variable is created on entry to its block and destroyed on exit. A static variable is created once, before main runs, and destroyed when the program ends:

Example04
CCode Cell
1#include <stdio.h>
2 
3void showAddresses(void)
4{
5 int automatic = 0;
6 static int persistent = 0;
7 
8 automatic++;
9 persistent++;
10 
11 printf("automatic = %d\n", automatic);
12 printf("persistent = %d\n", persistent);
13 printf("---\n");
14}
15 
16int main()
17{
18 showAddresses();
19 showAddresses();
20 showAddresses();
21 return 0;
22}
Output
automatic  = 1
persistent = 1
---
automatic  = 1
persistent = 2
---
automatic  = 1
persistent = 3
---

Linkage — Reaching Across Files

Linkage decides whether a name in one .c file refers to the same object as a name in another:

LinkageMeaningHow to get it
ExternalOne object shared by all filesA global, or extern
InternalPrivate to this filestatic at file scope
NoneNot shareable at allAny local variable
Example05
CCode Cell
1/* ---------- config.c ---------- */
2int maxUsers = 100; /* external linkage - shared */
3static int secretKey = 42; /* internal linkage - private */
4 
5/* ---------- main.c ---------- */
6#include <stdio.h>
7 
8extern int maxUsers; /* refers to the one in config.c */
9/* extern int secretKey; link error: it is static there */
10 
11int main()
12{
13 printf("maxUsers = %d\n", maxUsers);
14 maxUsers = 200; /* changes the same object */
15 printf("maxUsers = %d\n", maxUsers);
16 return 0;
17}
Output
maxUsers = 100
maxUsers = 200

Default Values Differ

Only static and global variables are zeroed automatically. A local variable holds whatever bytes happened to be on the stack. Code that works because an uninitialised local "happened to be 0" will fail the moment you add another function call before it — always initialise your locals.
Example06
CCode Cell
1#include <stdio.h>
2 
3int globalInt; /* zeroed by the C runtime */
4static int staticGlobal; /* zeroed too */
5 
6void show(void)
7{
8 static int staticLocal; /* zeroed */
9 /* int autoLocal; garbage - do not read it */
10 
11 printf("globalInt = %d\n", globalInt);
12 printf("staticGlobal = %d\n", staticGlobal);
13 printf("staticLocal = %d\n", staticLocal);
14}
15 
16int main()
17{
18 show();
19 printf("\nLocals are NOT zeroed - always initialise them.\n");
20 return 0;
21}
Output
globalInt    = 0
staticGlobal = 0
staticLocal  = 0

Locals are NOT zeroed - always initialise them.

Where Each One Lives in Memory

A running C program divides its memory into four regions. The storage class decides which one your variable goes to:

Example07
CCode Cell
1#include <stdio.h>
2#include <stdlib.h>
3 
4int initialisedGlobal = 42; /* data segment */
5int zeroedGlobal; /* BSS segment */
6 
7int main()
8{
9 int local = 1; /* stack */
10 int *heap = malloc(4); /* heap */
11 static int persistent = 7; /* data segment */
12 
13 if (heap == NULL) return 1;
14 *heap = 99;
15 
16 printf("Text : the compiled code itself\n");
17 printf("Data : initialisedGlobal=%d persistent=%d\n",
18 initialisedGlobal, persistent);
19 printf("BSS : zeroedGlobal=%d\n", zeroedGlobal);
20 printf("Heap : *heap=%d (yours until you free it)\n", *heap);
21 printf("Stack : local=%d (gone when main returns)\n", local);
22 
23 free(heap);
24 return 0;
25}
Output
Text  : the compiled code itself
Data  : initialisedGlobal=42 persistent=7
BSS   : zeroedGlobal=0
Heap  : *heap=99  (yours until you free it)
Stack : local=1  (gone when main returns)

static Means Two Different Things

This is the one genuine trap in the topic. The keyword changes lifetime inside a function, and linkage at file scope:

Example08
CCode Cell
1#include <stdio.h>
2 
3static int fileWide = 10; /* static HERE = private to this file */
4 
5void demo(void)
6{
7 static int calls = 0; /* static HERE = survives between calls */
8 calls++;
9 printf("call %d, fileWide %d\n", calls, fileWide);
10}
11 
12static void helper(void) /* static on a function = private too */
13{
14 printf("Only this file can call helper()\n");
15}
16 
17int main()
18{
19 demo();
20 demo();
21 helper();
22 return 0;
23}
Output
call 1, fileWide 10
call 2, fileWide 10
Only this file can call helper()

Storage Classes on Functions

Functions accept only static and extern. Functions are external by default, so extern on one is redundant:

Example09
CCode Cell
1#include <stdio.h>
2 
3extern void publicFn(void); /* 'extern' is redundant - the default */
4void alsoPublic(void); /* identical meaning */
5static void privateFn(void); /* invisible to other files */
6 
7void publicFn(void) { printf("publicFn: callable from any file\n"); }
8void alsoPublic(void) { printf("alsoPublic: same thing\n"); }
9static void privateFn(void) { printf("privateFn: this file only\n"); }
10 
11int main()
12{
13 publicFn();
14 alsoPublic();
15 privateFn();
16 return 0;
17}
Output
publicFn: callable from any file
alsoPublic: same thing
privateFn: this file only

Choosing One

In practice the decision is quick:

You wantUse
An ordinary local variableNothing — auto is the default
A value that survives between callsstatic inside the function
A helper private to this filestatic at file scope
A variable shared across filesDefine it once; extern in a header
Speed from a hot loop counterNothing — the optimiser beats register
Trainer's Note: in modern C you will write static often, extern occasionally in headers, and auto and register essentially never. That is not a gap in your knowledge — it is what current practice looks like.

Common Mistakes

  • Assuming locals start at zero — only static and global variables do.
  • Confusing the two meanings of static — lifetime in a function, linkage at file scope.
  • Defining a variable in a header — every including file gets its own copy or a duplicate-symbol error; declare it extern and define it in one .c.
  • Expecting extern int x = 5; in a header to work — an initialiser makes it a definition.
  • Confusing scope with lifetime — a static local still exists after the function returns; you simply cannot name it.
  • Reaching for register for speed — compilers have ignored it as a hint for decades.
📝 Key Takeaways
  • C has four storage classes: auto, register, static and extern.
  • They control three separate things: scope, lifetime and linkage.
  • auto is the default for locals and is almost never written.
  • static changes lifetime inside a function, and linkage at file scope.
  • extern declares something defined in another file.

🧠 Test Your Knowledge

4 Questions
Progress: 0 / 4