Storage Classes in C (auto, static, extern, register): Scope, Lifetime and Exam Questions

Separate scope, lifetime, storage duration and linkage, then use one static-versus-auto program and a two-file extern example to predict exam answers.

KnowledgeGate Team

Exam prep & CS education

Updated 15 Jul 20265 min read

Storage-class questions look like vocabulary questions, but they bundle several independent properties into one declaration. The usual mistake is to treat scope and lifetime as the same thing. Separate visibility, storage duration, linkage, initial value and likely storage location, and output questions become mechanical.

The attributes hiding inside every storage class

Five questions identify the behaviour of a C object:

  1. Where is its name visible? This is scope. A block-scope name cannot be used outside its block even if the object still exists.

  2. How long does the object exist? This is storage duration, often called lifetime in exam questions.

  3. Can the same name in another scope or file denote the same object? This is linkage.

  4. What is its initial value if no explicit initializer is written? Static-storage objects are zero-initialized. An uninitialized automatic object has an indeterminate value.

  5. Where is it usually stored? Exam diagrams commonly use a stack for automatic objects and the data or BSS area for static-storage objects. A compiler may optimise the physical placement.

The key separation is visible in a static local variable. Its name has block scope, so code outside the function cannot name it. Its object has static storage duration, so the value survives for the entire program.

The reference table for auto, register, static and extern

Declaration form

Usual exam storage model

No explicit initializer

Scope

Storage duration

Linkage

auto int x; inside a block

Stack

Indeterminate

Block

Until the block execution ends

None

register int x; inside a block

Register if chosen, otherwise implementation-managed

Indeterminate

Block

Until the block execution ends

None

static int x; inside a block

Data or BSS area

Zero

Block

Entire program

None

static int x; at file scope

Data or BSS area

Zero

File

Entire program

Internal

extern int x; referring to a file-scope definition

Data or BSS area for the defined object

Zero at the definition if no initializer appears

Scope of this declaration

Entire program

Usually external

Two details deserve precision. A static local has no linkage, not internal linkage. The static keyword gives internal linkage when used for a file-scope object or function. Also, extern does not make a name magically visible everywhere. Each source file needs a declaration in scope, while external linkage allows those declarations to refer to one object.

Applying the address operator to an object declared register is not allowed, even when the compiler would not actually keep it in a CPU register. Static-storage objects are zero-initialized before program execution. Automatic objects are not, so reading an uninitialized automatic int does not reveal a dependable "garbage value". Its value is indeterminate, and such a read can make the program's behaviour undefined.

Worked example: static counter versus auto counter

Consider this complete program:

#include <stdio.h>

void count(void)
{
    static int s = 0;
    int a = 0;

    s++;
    a++;
    printf("%d %d\n", s, a);
}

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

Its output is:

1 1
2 1
3 1

Trace the calls rather than memorising the output:

Call

s before s++

s printed

a before a++

a printed

1

0

1

0

1

2

1

2

0

1

3

2

3

0

1

The object s is initialized once and persists, so its stored value moves from 0 to 1, then 2, then 3. The name still exists only inside count. The automatic object a is created on each call and its initializer runs on each call. It therefore starts at 0 and becomes 1 three separate times.

a two-region memory picture. Left region "data segment" holds static int s with its value updating 0 -> 1 -> 2 -> 3 across the three calls (persists). Right region "stack frame of count()" holds auto int a, drawn as created and destroyed on each call, always going 0 -> 1. Arrows label "s survives between calls" and "a is reborn each call".

Linkage and extern: the part students skip

Suppose file1.c contains the definition:

int total = 0;

Then file2.c can refer to the same object through a declaration:

extern int total;

void add_one(void)
{
    total++;
}

The extern declaration tells the compiler that a compatible definition exists elsewhere. It normally does not allocate a second total. The program should have one external definition of that object. Placing int total = 0; in both files normally produces a multiple-definition linker error.

At file scope, int total; is a tentative definition in C. If no full definition for that name appears in the translation unit, it behaves as a zero-initialized definition. By contrast, extern int total; without an initializer is only a declaration.

If file1.c instead declares static int total;, the name has internal linkage. Code in another translation unit cannot use extern int total; to reach that object. File-scope static is therefore the standard tool for a file-private global object or helper function.

Traps that turn into wrong answers

  • Static initialization on every call: false. A static local is initialized once, and its value persists between calls.

  • Every local starts at zero: false. An uninitialized automatic or register object has an indeterminate value.

  • A register variable always sits in a CPU register: false. The keyword is a request that modern compilers may ignore, but applying & to that declared object is still invalid.

  • Long lifetime means wide scope: false. A static local lives throughout the program and remains nameable only in its block.

  • extern is a definition: usually false when it is a declaration without an initializer. It refers to storage defined elsewhere.

  • Duplicate global definitions are compile-time syntax errors: false. Individual files can compile, while the conflict normally appears when the linker combines them.

Answer each property independently. If a question asks about visibility, do not answer from storage duration. If it asks whether memory persists, do not answer from scope.

How GATE tests storage classes

GATE can ask you to predict a static-counter output, match declarations with scope and duration, identify a default initialization rule, or spot a program that fails because it takes the address of a register object. Multi-file snippets test the difference between declaration, definition and linkage.

The fastest method is to annotate every variable with five labels: scope, duration, linkage, initialization and relevant constraint. Then execute the program call by call. For the exact Programming and Data Structures syllabus wording, use the official GATE 2026 portal of the organising IIT.

KnowledgeGate's question bank has about 900 published C-programming questions, giving you enough scope and output cases to turn those labels into a habit.

The short version and the next step

A static local is the fact to remember: block scope, static storage duration, no linkage, one initialization and a value that survives calls. Automatic and register objects have automatic duration, while file-scope static objects have internal linkage and extern declarations can name an externally linked object.

Next, connect these declarations to addresses and memory using Pointers in C for GATE, then place them in the broader C programming for CS teaching exams map. Build the full sequence with the C Programming course and use the Coding Skills category to continue into related topics.