Variable lifetimes Ready
main.c

                

Ready

Statements run 0 Lines printed 0
Ready

Keyboard: ← → step · Space play / pause · R reset · Esc exit classroom mode

How it works

The ideas behind the lab

Exactly what you watched happen, in plain steps.

Two questions about every variable

Scope answers "where in the code can I use this name?" — from its declaration to the end of its block, or the whole file for a global. Lifetime answers "how long does the variable exist?" — an ordinary local lives while its block or call runs (on the stack); a global or static variable lives for the whole run (in global memory). The storage class keywords auto, static, extern and register change these rules.

int g;                  // global: whole file, whole run, starts at 0

void f(void)
{
    int a = 1;          // local (auto): only in f, only during the call
    static int s = 0;   // static local: only in f, but for the whole run
    {
        int b = 2;      // block scope: only inside these { }
    }
}
Storage classes
Keyword Where Scope (visible) Lifetime Starts as
auto (default) inside a function / block its block while the block runs garbage
register inside a function its block while the block runs garbage (and no &)
static (local) inside a function its block the whole run 0, set once
(none) global outside all functions the rest of the file (+ other files with extern) the whole run 0
static (global) outside all functions this file only the whole run 0
extern anywhere declares a global defined elsewhere — —

Local and global

  1. A local variable is declared inside a function or block.
  2. It can be used only there, and is created again on every call.
  3. An uninitialised local holds garbage — always give it a value.
  4. A global variable is declared outside all functions and starts at 0.
  5. Every function below it can read and change it — convenient but risky.

Blocks and shadowing

  1. Every { } is a block; a variable declared in it lives until the matching }.
  2. for (int i = 0; …) — this i exists only inside the loop.
  3. An inner variable with the same name hides (shadows) the outer one.
  4. C always uses the nearest declaration of a name.
  5. Shadowing is legal but confusing: choose different names.

static, extern and register

  1. static int n = 0; inside a function: set up once, keeps its value between calls.
  2. Use it for counters and "has this run before?" flags.
  3. static in front of a global or a function: visible only in that .c file.
  4. extern int total; says "total is defined in another file — use that one".
  5. register asks for a CPU register; compilers ignore it today, and you cannot take its address.
Walkthrough

A global counter, a static id and loop-only variables

Every line, explained.

1 #include <stdio.h>
2
3 int calls = 0; Global: every function below can use it.
4
5 int nextId(void)
6 {
7 static int id = 100; Made once, before main. NOT reset on each call.
8 calls++; Changes the global.
9 return ++id; 101, then 102, then 103.
10 }
11
12 int main(void)
13 {
14 for (int i = 0; i < 3; i++) { i exists only inside this loop.
15 int id = nextId(); Another variable called id — local to the loop body.
16 printf("%d ", id); Prints 101 102 103
17 }
18 printf("\ncalls = %d\n", calls); Prints calls = 3
19 return 0;
20 }
Common mistakes

Spot the bug

Mistakes almost every beginner makes — and how to fix them.

Using a variable outside its block

✗ Wrong
for (int i = 0; i < 5; i++) { }
printf("%d", i);   // error
✓ Right
int i;
for (i = 0; i < 5; i++) { }
printf("%d", i);   // 5

A variable declared in the for or in a block is gone after it: "'i' undeclared".

Expecting a local to remember its value

✗ Wrong
void count(void) {
    int n = 0;
    n++;   // always 1
}
✓ Right
void count(void) {
    static int n = 0;
    n++;   // 1, 2, 3 …
}

An ordinary local is created again on every call. static keeps it alive between calls.

Uninitialised local variables

✗ Wrong
int sum;
sum += 5;   // garbage + 5
✓ Right
int sum = 0;
sum += 5;

Globals and statics start at 0, but locals contain whatever was in that memory before.

Shadowing by accident

✗ Wrong
int total = 0;
for (…) { int total = 0; total += x; }
// outer total is still 0
✓ Right
int total = 0;
for (…) { total += x; }

The inner int total is a new variable that hides the outer one; it vanishes after each round.

Using globals for everything

✗ Wrong
int a, b, result;   // global
void add(void) { result = a + b; }
✓ Right
int add(int a, int b) { return a + b; }

Any function can change a global, so bugs are hard to find. Pass parameters and return values instead.

Practice

Check your understanding

Answer each question — you will see the explanation straight away.

0 / 5 correct
Question 1

Where can a local variable declared in main be used?

Question 2

What is the starting value of an uninitialised global int?

Question 3

void f(void) { static int n = 0; n++; printf("%d ", n); } — f(); f(); f(); prints?

Question 4

int x = 1; { int x = 2; } printf("%d", x); prints?

Question 5

What does extern int count; do?

Assessment

Scope, Lifetime & Storage Classes quiz

Test yourself: 10 questions, 70% to pass. Create a free account to take the quiz, save your progress and work towards the certificate.