Storage Classes in C: Worked Examples for Scope, Lifetime, Linkage and GATE Traps

Learn what auto, register, static and extern actually control. Classification tables, two-file code and exact traces turn similar-looking declarations into predictable C behaviour.

KnowledgeGate Team

Exam prep & CS education

Updated 14 Sep 20266 min read

static may name a block-scoped object that survives calls or a file-scoped object hidden from other files. extern may declare a name without defining another object. Classify each declaration by scope, storage duration and linkage, then trace the calls to obtain 5 5 7, 5 8 8 and 5 11 9.

Storage classes in C: scope, storage duration and linkage

Three separate questions organise this topic:

  • Scope: Where can this name be used in the source text?

  • Storage duration: How long does the object exist? Learners often call this lifetime.

  • Linkage: Do declarations in the same or different translation units denote the same entity?

Declaration context matters, so a keyword alone cannot answer all three questions.

Exact declaration

Scope

Storage duration

Linkage

auto int a = 2; inside a block

Block

Automatic

None

register int r = 4; inside a block

Block

Automatic

None

static int s = 2; inside a function

Block

Static

None

static int hidden = 4; at file scope

File

Static

Internal

extern int total; at file scope

File

Static for the referred object

External

The final row refers to the single object defined in another file. auto, register, static and extern are the four conventional runtime-focused storage classes. C grammar also classifies typedef as a storage-class specifier, while C11 added _Thread_local for per-thread storage.

Table classifying five C declarations by scope, storage duration and linkage: auto, register, block static, file static and extern.

auto and register: automatic objects without the folklore

A block-scope object is automatic by default. Therefore, int a = 2; and auto int a = 2; have the same storage duration. Each execution of the block creates a fresh a; it starts at 2, becomes 5, then ceases to exist when execution leaves.

register int r = 4; also has block scope, automatic storage duration and no linkage. register is only an access-speed hint. An implementation need not put r in a CPU register, but C still does not permit &r.

This deterministic check prints 6:

c
register int r = 4;
auto int a = 2;
printf("%d\n", r + a);

Do not extend that predictability to int x; without an initializer. An uninitialised automatic integer has an indeterminate value. It is not automatically zero, and no guessed numeric output is valid.

static in C: retained local state versus internal linkage

Inside a function, static int s = 2; gives s block scope and no linkage, but the object has static storage duration and is initialised only once. At file scope, static int hidden = 4; instead gives the name internal linkage. Another source file cannot name that same object.

Consider int next(void) { static int n = 10; n += 2; return n; }. Three calls return 12, 14 and 16. Replace the declaration with int n = 10;, and all three calls return 12 because each call creates a new automatic object.

Objects with static storage duration are initialised before program start. Without an explicit initializer, arithmetic objects are zero-initialised. Thus, file-scope int total; and block-scope static int hits; both begin at 0. Block-scope automatic int temp; remains indeterminate until assigned.

extern in C: one definition shared across source files

Suppose counter.c contains:

c
int total = 12;
static int hidden = 4;

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

Now main.c contains extern int total; and int add(int);. Printing total first gives 12. After int result = add(5);, printing result and total gives 17 17.

extern int total; refers to the object defined once in counter.c; it does not create a second total. The linker resolves that external-linkage name across translation units. If main.c instead declares extern int hidden; and uses it, no external definition matches because the hidden in counter.c has internal linkage. Linking fails.

Keep the declaration and definition boundary exact. Here, extern int total; without an initializer is a declaration, while int total = 12; is the definition. An extern declaration with an initializer is itself a definition, so the shortcut “extern never defines storage” is false.

Worked storage-class trace: auto resets, static retains, global state changes

Trace this program statement by statement:

c
#include <stdio.h>

int g = 7;

void tick(void) {
    auto int a = 2;
    static int s = 2;
    a += 3;
    s += 3;
    printf("%d %d %d\n", a, s, g);
    g++;
}

int main(void) {
    tick();
    tick();
    tick();
    return 0;
}

On call 1, new a goes from 2 to 5. The once-initialised s goes from 2 to 5. The program prints g as 7, then increments it to 8. The first line is 5 5 7.

On call 2, another new a becomes 5. Retained s goes from 5 to 8. The program prints g as 8, then increments it to 9. The second line is 5 8 8.

On call 3, a again becomes 5, retained s goes from 8 to 11, and g prints as 9 before becoming 10. The third line is 5 11 9.

Code
5 5 7
5 8 8
5 11 9

So a has block scope, automatic duration and no linkage. s has block scope, static duration and no linkage. File-scope g has static duration and external linkage by default.

State trace of the tick program over three calls: a resets to 5 each time, static s rises 5, 8, 11, and global g prints 7, 8, 9.

Storage-class traps: initialization, shadowing and invalid assumptions

  • Mistake: “static means global.” Consequence: A block-scope static is misclassified. Correction: It keeps block scope but has static duration.

  • Mistake: “extern creates a copy.” Consequence: A two-file trace gains two imagined totals. Correction: The declaration refers to one externally linked definition.

  • Mistake: “uninitialised objects are zero.” Consequence: Code reads an indeterminate automatic int x. Correction: static int s; and file-scope int g; begin at 0, but block-scope automatic int x; must be assigned before reading.

Shadowing is separate. With file-scope int x = 9;, a function that declares int x = 3; prints 3 inside that block. The outer object remains 9. Shadowing changes which declaration the name denotes, not either object's storage duration.

Two more checks catch common exam traps. register int r = 4; int *p = &r; violates the address rule for a register object. extern int missing; may compile when used, but linking fails if the program provides no definition.

How GATE-style questions test storage classes in C

GATE-style tasks classify declarations, trace repeated calls with a block static, compare zero-initialised static-duration objects with indeterminate automatic ones, follow one external object across files, and distinguish compile-time constraints from link failures.

Try a 60-second drill: change static int s = 2; to static int s = 1; and call tick() four times. a stays 5; s becomes 4, 7, 10, 13; g prints 7, 8, 9, 10. The lines are 5 4 7, 5 7 8, 5 10 9 and 5 13 10.

IIT Guwahati's GATE 2026 Computer Science and Information Technology syllabus places “Programming in C” in Section 4. That scope statement does not imply a fixed mark share or yearly frequency. The definition-first reference table and short exam questions belong to Storage Classes in C (auto, static, extern, register): Scope, Lifetime and Exam Questions. The two-file extern case and three-call state trace train execution instead. Use the GATE CS Exam category for broader preparation and MCQ, MSQ or NAT? GATE Question Types Explained for answer-format technique.

Storage classes in C: the short version and next step

Use a four-part routine: find the declaration context, mark the name's scope, mark the object's automatic or static duration, then decide whether linkage is none, internal or external. In the trace, a resets to 2, s retains its prior value, and externally linked g advances from 7 to 10 after three calls.

For a compact language-first route, use the C Programming course. For a broader GATE sequence containing C Language, Storage Classes, Structures and Enums, use GATE Guidance by Sanchit Sir. They are alternative starting points, so choose the route that matches your present goal.