C Scope, Storage Duration and static Locals
C Scope, Storage Duration and static Locals
A ticket helper needs to remember the previous ticket number, while each call also needs temporary calculations. Visibility and lifetime answer different questions.
Scope determines where an identifier can be used. Storage duration determines how long an object exists. An automatic local usually belongs to one call; a static local persists for the whole program execution.
Explain
Distinguish an object’s lifetime from the places where its name is visible.
Trace
Make three successive calls and predict all ticket numbers.
Apply
Distinguish where a name is visible from how long its value exists.
Scope and Lifetime: follow the data
Start
A ticket helper needs to remember the previous ticket number, while each call also needs temporary calculations. Visibility and lifetime answer different questions.
Operation
Scope determines where an identifier can be used. Storage duration determines how long an object exists. An automatic local usually belongs to one call; a static local persists for the whole program execution.
Result
Ticket: 1 Ticket: 2
Understand the operation
last is visible within next_ticket but persists across completed calls. Its initializer supplies the starting value once rather than resetting the number on every call. A plain automatic int last = 0 would be recreated for each call.
The static keyword has another role at file scope: it can give a function or object internal linkage, limiting that name’s linkage to the translation unit. Do not confuse that visibility/linkage use with the local lifetime example.
Read the complete C program
This complete C17 program uses a small school example. Read declarations before the statements that use their values. Each printf format describes how the corresponding value is written to standard output.
C17 · complete program
#include <stdio.h>
static int next_ticket(void) {
static int last = 0;
last++;
return last;
}
int main(void) {
printf("Ticket: %d\n", next_ticket());
printf("Ticket: %d\n", next_ticket());
return 0;
}
Expected output
Ticket: 1
Ticket: 2
Run in C compiler →Follow the values through the code
C17 · code used in this explanation
#include <stdio.h>
static int next_ticket(void) {
static int last = 0;
last++;
return last;
}
int main(void) {
printf("Ticket: %d\n", next_ticket());
printf("Ticket: %d\n", next_ticket());
return 0;
}
The first call increments the persistent last from zero to one.
After it returns, last still exists; the next call increments the same object to two.
Follow the worked calculation
Read the starting values
The first call increments the persistent last from zero to one.
Perform the operation
After it returns, last still exists; the next call increments the same object to two.
Check the observable result
Ticket: 1 Ticket: 2
Ticket: 1 Ticket: 2
Try a small variation
C17 · code used in this explanation
#include <stdio.h>
static int next_ticket(void) {
static int last = 0;
last++;
return last;
}
int main(void) {
printf("Ticket: %d\n", next_ticket());
printf("Ticket: %d\n", next_ticket());
return 0;
}
Make three successive calls and predict all ticket numbers.
Worked answer
Each loop iteration calls the helper once. The static object retains the previous value between iterations, unlike the loop’s automatic counter.
C17 · complete program
#include <stdio.h>
static int next_ticket(void) {
static int last = 0;
last++;
return last;
}
int main(void) {
for (int i = 0; i < 3; i++) printf("Ticket: %d\n", next_ticket());
return 0;
}
Expected output
Ticket: 1
Ticket: 2
Ticket: 3
Run in C compiler →Recognize the important boundaries
Persisting a counter does not make its updates thread-safe. Shared mutable objects need a concurrency design when multiple threads can access them.
Do not return an automatic local object’s address. Leaving its scope and ending its lifetime are concepts that need to be checked together.
Check your understanding
Choose the answer, then compare the reasoning for every option.
Use the idea independently
Scope determines where an identifier can be used. Storage duration determines how long an object exists. An automatic local usually belongs to one call; a static local persists for the whole program execution.
Continue with linkage and module contracts.
Language reference: WG14 C11 committee draft. These examples use the C17-compatible subset of the explained language features.
Reaching the recap and completing the quizzes are separate milestones.