๐Ÿ’พ Storage Classes in C

A storage class in C helps describe important properties associated with an identifier, such as its scope, storage duration, and, where relevant, linkage.

Understanding storage classes is essential when working with functions, multiple source files, global variables, recursion, static data, and larger C projects.

Core idea: Do not think of a storage class simply as "where a variable is stored in RAM." Storage-class specifiers primarily affect how an identifier behaves in terms of visibility, lifetime, linkage, and related declaration rules.

21.1 Why Storage Classes Matter

Consider these two variables:

int local = 10;

and:

static int count = 0;

Both are integers, but their behavior can be very different.

  • A normal local variable generally has automatic storage duration.
  • A static local variable retains its stored value between function calls.
  • An external declaration can refer to an object defined elsewhere.
  • register expresses a request to keep an object in a register when supported by the implementation, but it does not guarantee this.

21.2 The Four Traditional Storage-Class Specifiers

Specifier Typical Context Important Property
auto Block-scope local variables Automatic storage duration
register Block-scope objects / parameters in applicable declarations Requests register storage; implementation may ignore the request
static Block scope and file scope Static storage duration; file-scope use also affects linkage
extern Declarations referring to externally defined objects/functions Declares an identifier without necessarily defining the object
Important: The meaning of static depends on where it appears. A block-scope static object and a file-scope static object both have static storage duration, but their visibility/linkage behavior is different.

21.3 Scope, Lifetime, Storage Duration and Linkage

These terms are often mixed together. They describe different properties.

Scope

The region of program text in which an identifier can be used to refer to the declared entity.

Storage Duration

Describes how long the storage associated with an object exists.

Linkage

Describes whether declarations of an identifier in different scopes or translation units can refer to the same entity.

21.4 The Four Storage Durations

Storage Duration Meaning Typical Example
Automatic Storage exists for execution of the relevant block. Ordinary local variable
Static Storage exists for the entire execution of the program. Global or static local object
Allocated Storage is obtained dynamically and lasts until released or otherwise ceases to be available. malloc()-allocated object
Thread Storage duration associated with a thread. _Thread_local

Allocated storage duration is covered more deeply in the Dynamic Memory Allocation topic. Thread storage duration is an advanced C feature and is outside the main focus of this lesson.

21.5 The auto Storage Class

The auto specifier indicates automatic storage duration for an object declared at block scope.

int main(void) { auto int x = 10; printf("%d\n", x); return 0; }

In ordinary modern C programming, the keyword auto is rarely written explicitly because block-scope variables already have automatic storage duration by default when no other storage-class specifier changes it.

21.6 Automatic Variables

This is more common:

int main(void) { int x = 10; printf("%d\n", x); return 0; }

Here x is an automatic-duration object because it is an ordinary block-scope local variable.

Remember: "Automatic" does not mean "initialized automatically to zero." An automatic variable with no initializer has an indeterminate value.

21.7 Example of Automatic Lifetime

void demo(void) { int x = 10; printf("%d\n", x); }

Each time demo() is entered, a new instance of the automatic object x is created for that execution of the block. Its storage duration ends when execution leaves the block.

21.8 Automatic Variables and Initialization

int main(void) { int a; int b = 20; printf("%d\n", b); return 0; }

b has a specified initial value. a does not. Reading a before giving it a valid value can produce undefined behavior in contexts where its indeterminate value is used inappropriately.

21.9 The register Storage Class

The register keyword historically expresses a request that an object be stored in a processor register if possible.

int main(void) { register int i; for (i = 0; i < 10; ++i) { printf("%d ", i); } return 0; }
Modern compilers perform their own optimization decisions. Writing register does not guarantee that the object will actually reside in a hardware register.

21.10 Important Rule About register

A particularly important language rule is that you cannot apply the unary address-of operator to an object declared with the register storage-class specifier.

register int x = 10; /* Not allowed: */ int *p = &x;

The language specifically restricts taking the address of a register-declared object.

21.11 Should You Use register Today?

Usually, programmers should focus on writing clear code and let the compiler optimizer make register-allocation decisions.

The keyword remains part of the language, so it is still important for exams and for understanding older C code.

21.12 The static Storage Class

The keyword static has two especially important uses:

  1. At block scope, it gives the object static storage duration.
  2. At file scope, it gives an object or function internal linkage.
This distinction is extremely important for interviews. Do not memorize "static means global." It does not.

21.13 Static Local Variable

void counter(void) { static int count = 0; count++; printf("%d\n", count); }

If called three times:

counter(); counter(); counter();

the output is:

1 2 3

The local name count remains visible only inside the function, but the object retains its value between calls.

21.14 Static Local Variable Trace

 First call | โ–ผ count = 0 | โ–ผ count++ | โ–ผ prints 1 Second call | โ–ผ same static object | โ–ผ count = 1 | โ–ผ count++ | โ–ผ prints 2 Third call | โ–ผ count = 2 | โ–ผ count++ | โ–ผ prints 3 

21.15 Static Local vs Normal Local

Property Normal Local Static Local
Scope Block Block
Storage duration Automatic Static
Retains value between calls? No Yes
Initialized when? Each entry/creation as applicable Once before program execution reaches the object
Default initialization Indeterminate if no initializer Zero-initialized if no explicit initializer

21.16 Static Local Initialization

void demo(void) { static int x = 10; x += 5; printf("%d\n", x); }

Repeated calls produce:

15 20 25 

The initializer is not reapplied as though the object were newly created on every function call.

21.17 Static Local Variables in Recursion

Static local variables can produce behavior very different from automatic variables during recursion.

void countDown(int n) { static int calls = 0; calls++; if (n > 0) { countDown(n - 1); } printf("Calls = %d\n", calls); }

All recursive invocations refer to the same static object calls, not separate copies.

An automatic local variable normally gets a separate instance for each active function invocation. A static local object is a single object whose storage persists for the entire program execution.

21.18 Static at File Scope

Consider:

static int counter = 0;

At file scope, this object has static storage duration and internal linkage.

That means declarations in other translation units cannot refer to this object by ordinary external linkage.

21.19 Static File-Scope Function

static void helper(void) { printf("Internal helper\n"); }

A file-scope function declared static has internal linkage. It is intended to be usable within that translation unit rather than exported through external linkage.

21.20 Why File-Scope Static Is Useful

  • Hides implementation details from other source files.
  • Reduces accidental name collisions across translation units.
  • Helps create private helper functions and private file-level objects.
  • Makes module boundaries clearer.

21.21 Internal vs External Linkage

Linkage Meaning
None The identifier does not denote the same entity through declarations in other scopes in the linkage sense.
Internal Declarations in the same translation unit can refer to the same entity.
External Declarations in different translation units can refer to the same entity when the linkage rules allow it.

21.22 What Is a Translation Unit?

A translation unit is essentially the source file after preprocessing, including the relevant contents brought in through preprocessing directives.

 source.c | | preprocessing v translation unit | | compilation v object file | | linking v executable 

21.23 The extern Storage Class

The extern keyword is commonly used to declare that an object or function is defined elsewhere.

Example:

extern int total;

This declaration says that total is an object with external linkage and that its definition is provided elsewhere, subject to the applicable language rules.

21.24 Declaration vs Definition

This distinction is critical when learning extern.

extern int total;

is normally a declaration that does not define the object.

Whereas:

int total = 100;

is a definition of the object.

Simple rule: A declaration tells the compiler about an entity. A definition provides the entity itself when the language construct requires storage or a function body.

21.25 Multi-File Example

counter.c

int total = 100;

main.c

#include <stdio.h> extern int total; int main(void) { printf("%d\n", total); return 0; }

The definition of total is in one translation unit and its declaration is visible in the other.

21.26 Header Files and extern

In a multi-file project, an external declaration is often placed in a header.

config.h

#ifndef CB_CONFIG_H #define CB_CONFIG_H extern int total; #endif

config.c

#include "config.h" int total = 100;

main.c

#include <stdio.h> #include "config.h" int main(void) { printf("%d\n", total); return 0; }
This separation keeps declarations and definitions organized and is common in larger C programs.

21.27 Do Not Define Ordinary Global Objects Repeatedly in Headers

A common mistake is putting an ordinary external definition directly into a header:

/* Bad header design */ int total = 100;

If that header is included by multiple translation units, multiple definitions of the same external object can cause linker errors.

A common pattern is:

/* header */ extern int total; /* exactly one .c file */ int total = 100;

21.28 Static vs Extern

Feature static at File Scope extern
Typical purpose Keep entity private to translation unit Refer to externally linked entity
Linkage Internal External
Common use Private helper function/object Shared declaration across source files

21.29 Static Function vs Normal Function

static void calculate(void) { /* private helper */ }

Compared with:

void calculate(void) { /* externally linked function */ }

At file scope, static gives the function internal linkage. A normal file-scope function definition normally has external linkage unless another rule changes it.

21.30 Static Does Not Mean Constant

Common mistake: Thinking static means "cannot change."

It does not.

static int count = 0; count++; count++; 

The value can change normally.

If you want an object that cannot be modified through its declared type, const is relevant.

21.31 Static Does Not Mean Global

Consider:

void demo(void) { static int x = 10; }

The object has static storage duration, but its identifier has block scope. It is not a globally visible variable.

21.32 Static Initialization

Objects with static storage duration are initialized before program startup according to C's initialization rules.

static int a; static int b = 20;

If no initializer is supplied, an object with static storage duration is initialized to zero (or the appropriate null/zero representation for its type).

21.33 Automatic vs Static Initialization

Object No Explicit Initializer
int x; inside a function Indeterminate value; do not read it before giving it a valid value.
static int x; Initialized to zero.
File-scope int x; Initialized to zero.

21.34 Storage Class and Scope Are Different

Consider:

int global; void demo(void) { int local; static int persistent; }
Identifier Scope Storage Duration
global File Static
local Block Automatic
persistent Block Static

21.35 Storage Class and Memory Location

A beginner-friendly diagram might show:

 Program Memory โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ โ–ผ โ–ผ โ–ผ Static-duration Automatic Allocated objects objects objects โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ global/static local data malloc/calloc objects in blocks /realloc 

This is a conceptual model, not a guarantee of a specific physical memory layout. The C language defines behavior and storage duration; the exact machine-level arrangement is implementation-dependent.

21.36 Storage Classes and Functions

Storage-class specifiers also appear in function declarations and definitions, but their meaning must be interpreted according to context.

The most common example is:

static void helper(void) { }

where static at file scope gives the function internal linkage.

21.37 The extern Keyword With Functions

Functions normally have external linkage unless their declaration is made static.

Therefore an explicit:

extern void display(void);

can declare an externally linked function defined elsewhere.

Because external linkage is the normal case for ordinary file-scope functions, explicit extern is often unnecessary for function declarations.

21.38 Storage-Class Specifiers vs Type Qualifiers

Category Examples Purpose
Storage-class specifiers auto, register, static, extern Describe storage duration/linkage and related declaration properties.
Type qualifiers const, volatile, restrict, _Atomic Qualify the type or access semantics.
static and const are not interchangeable. One is a storage-class specifier; the other is a type qualifier.

21.39 What About _Thread_local?

Modern C also provides the _Thread_local storage-class specifier for objects whose storage duration is associated with a thread.

_Thread_local int thread_count;

Each thread can have its own instance of the object.

This is an advanced topic and is mainly relevant to multithreaded C programs.

21.40 Complete Comparison

Specifier Typical Scope Storage Duration Linkage Effect Typical Use
auto Block Automatic None Explicitly request automatic duration; rarely written.
register Block Automatic None Historical optimization hint; address cannot be taken.
static at block scope Block Static None Preserve local state between calls.
static at file scope File Static Internal Hide object/function within translation unit.
extern File/block declarations as applicable Usually refers to static-duration object/function External Declare an entity defined elsewhere.

21.41 Example โ€” Four Concepts Together

#include <stdio.h> int global_value = 100; static int private_value = 200; void demo(void) { int local_value = 10; static int persistent_value = 0; persistent_value++; printf("%d %d %d %d\n", global_value, private_value, local_value, persistent_value); } int main(void) { demo(); demo(); return 0; }

Important observations:

  • global_value has static storage duration and external linkage.
  • private_value has static storage duration and internal linkage.
  • local_value has automatic storage duration.
  • persistent_value has static storage duration but block scope.

21.42 Program Trace

 Program starts global_value = 100 private_value = 200 persistent_value = 0 | โ–ผ First demo() local_value = 10 persistent_value++ persistent_value = 1 Output: 100 200 10 1 | โ–ผ demo() ends local_value disappears persistent_value remains 1 | โ–ผ Second demo() new local_value = 10 persistent_value++ persistent_value = 2 Output: 100 200 10 2 

21.43 Why Does Static Local Remember?

The key is storage duration.

static int count = 0;

The object continues to exist after the function block finishes, even though the identifier count is only usable within that block.

 Scope โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function block only Storage duration โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ entire program execution Therefore: name is local object lifetime is persistent 

21.44 Static Local Counter Pattern

This is a common practical pattern:

int next_id(void) { static int id = 1000; return id++; }

Repeated calls return:

1000 1001 1002 1003 ...

This pattern can be useful for maintaining state without exposing the variable as a global object.

21.45 Static Function for Module Encapsulation

static int square(int x) { return x * x; }

If the function is defined at file scope with static, it is private to that translation unit in terms of linkage.

This is useful for helper functions that should not become part of a module's external interface.

21.46 A Typical Header/Source Design

student.h

#ifndef CB_STUDENT_H #define CB_STUDENT_H typedef struct { int id; char name[50]; } Student; void printStudent(const Student *student); #endif

student.c

#include <stdio.h> #include "student.h" static void printSeparator(void) { printf("----------------\n"); } void printStudent(const Student *student) { printSeparator(); printf("ID: %d\n", student->id); printf("Name: %s\n", student->name); }

Here printSeparator() is a private helper because it is file-scope static.

21.47 Why This Design Is Useful

  • The header exposes the public interface.
  • The source file contains the implementation.
  • The static helper is hidden from other translation units.
  • Other files can use printStudent() through the header.

21.48 Common Storage-Class Mistakes

  • Thinking static always means global.
  • Thinking static means constant.
  • Thinking register guarantees a CPU register.
  • Thinking auto initializes local variables to zero.
  • Thinking extern creates the actual global object.
  • Defining the same external object in multiple source files.
  • Putting ordinary external variable definitions in widely included headers.
  • Confusing scope with storage duration.
  • Confusing storage duration with physical RAM location.
  • Assuming a static local variable becomes globally accessible.

21.49 Common Confusions

Confusion 1: "static variable is a global variable."

Correction: A block-scope static variable remains local in scope but has static storage duration.

Confusion 2: "extern creates a variable."

Correction: An extern declaration normally refers to a definition elsewhere.

Confusion 3: "register means the variable is definitely stored in CPU register."

Correction: It is a request/hint; the implementation decides actual storage and optimization.

Confusion 4: "static means immutable."

Correction: Static objects can be modified unless they are separately declared with appropriate type qualification such as const.

Confusion 5: "local variable is always zero."

Correction: An uninitialized automatic object has an indeterminate value.

21.50 Storage Classes and Recursion

Consider a normal recursive function:

void recurse(int n) { int local = n; if (n > 0) recurse(n - 1); }

Each active invocation has its own automatic local object.

With:

static int local;

there is one static object shared by all invocations of the function.

 Automatic recursion: Call 1 โ†’ local A Call 2 โ†’ local B Call 3 โ†’ local C Static recursion: Call 1 โ”€โ” Call 2 โ”€โ”ผโ”€โ”€โ–บ one static object Call 3 โ”€โ”˜ 

21.51 Storage Duration Is Not Stack/Heap Terminology

You may hear programmers say:

automatic = stack allocated = heap static = data segment 

These are useful implementation-level mental models, but they are not the complete language definition.

For portable C reasoning, focus first on the language concepts: scope, storage duration, linkage, initialization, and lifetime. Do not assume a particular physical memory segment unless the implementation documentation guarantees it.

21.52 Interview Question โ€” static Local

#include <stdio.h> void test(void) { static int x = 0; x++; printf("%d ", x); } int main(void) { test(); test(); test(); return 0; }

Output:

1 2 3

Reason: the same static object persists between calls.

21.53 Interview Question โ€” Automatic Local

#include <stdio.h> void test(void) { int x = 0; x++; printf("%d ", x); } int main(void) { test(); test(); test(); return 0; }

Output:

1 1 1

The automatic local object is initialized to zero for each invocation.

21.54 Interview Question โ€” File-Scope static

static int count = 10;

At file scope, count has internal linkage. Another translation unit cannot access that object through an ordinary external declaration of the same identifier.

21.55 Interview Question โ€” extern

Suppose:

/* file1.c */ int value = 50;

and:

/* file2.c */ extern int value;

The second declaration allows code in file2.c to refer to the externally linked object defined in file1.c.

21.56 Interview Question โ€” register Address

register int x = 10; printf("%p", (void *)&x);

This is not valid C because the address of a register-declared object cannot be taken.

21.57 Storage Class Decision Tree

 Do you need ordinary local state? | โ”œโ”€โ”€ Yes โ†’ automatic object | โ–ผ Do you need local state to survive function calls? | โ”œโ”€โ”€ Yes โ†’ static local | โ–ผ Do you want a file-private object/function? | โ”œโ”€โ”€ Yes โ†’ file-scope static | โ–ผ Do you need to refer to an external definition? | โ”œโ”€โ”€ Yes โ†’ extern declaration | โ–ผ Do not use register merely to force optimization. Let the compiler optimize. 

21.58 Best Practices

  • Prefer ordinary local variables unless persistent local state is actually needed.
  • Use static locals deliberately when state should survive calls but remain encapsulated.
  • Use file-scope static to keep implementation details private to a source file.
  • Use headers for declarations and source files for definitions where appropriate.
  • Use extern for declarations of externally linked entities rather than duplicating definitions.
  • Do not depend on register for performance.
  • Do not describe storage classes solely as physical memory locations.

22.15 Quick Revision

๐Ÿ“Œ auto โ†’ Default for ordinary local variables.

๐Ÿ“Œ register โ†’ Requests register-oriented optimization; compiler may ignore the request.

๐Ÿ“Œ static local โ†’ Retains value between function calls.

๐Ÿ“Œ static file-scope โ†’ Internal linkage.

๐Ÿ“Œ extern โ†’ Declares an object/function defined with appropriate linkage elsewhere.

๐Ÿ“Œ Scope โ†’ Where the name can be used.

๐Ÿ“Œ Lifetime โ†’ How long the object exists.

๐Ÿ“Œ Linkage โ†’ Whether declarations in different scopes/files can refer to the same entity.
INTERACTIVE LEARNING

๐ŸŽฌ Storage Classes โ€” Scope, Lifetime & Linkage

Compare the key idea behind auto, register, static, and extern.

PROGRAM TRACING

๐Ÿ”Ž Program Tracing โ€” Storage Classes

Compare an automatic local variable that is created for each call with a static local variable that retains its value between calls.

22.16 Quick MCQs

Select an answer first, then click Check Answer. A correct choice becomes green. If the answer is wrong, your choice becomes red and the correct option becomes green. The explanation appears below.

1. Which storage class is the default for ordinary local variables?
2. Which keyword allows a local variable to retain its value between function calls?
3. Which keyword declares a reference to an object defined elsewhere?
4. Which keyword can be used for a file-scope function to give it internal linkage?
5. An uninitialized static-duration int object is initialized to:
6. Which keyword does not guarantee that a variable will be stored in a CPU register?
7. A static local variable has:
8. Which concept describes how long an object exists?
9. File-scope static variables generally have:
10. Does an extern declaration necessarily define a new object?
PRACTICE

22.17 ๐ŸŽฏ Practice Problems

Practice auto, register, static locals, file-scope static names, extern, scope, lifetime, linkage, and multi-file design concepts. Use ๐Ÿ’ป Solve It Yourself first, open Hint only when needed, and use Show Program after attempting the problem.

๐Ÿ“ˆ Storage Classes Practice Progress
Solved 0 / 20
Completed with Solution 0
Total Score 0 / 2000
Completion 0%
A problem counts as Solved when all test cases pass without opening the full solution. Problems completed after viewing the official solution are tracked separately.
1. Purpose of auto

Problem 1: Explain the purpose of the auto storage class using a runnable program.

Input: No input.

Output: Print a concise explanation.

2. Automatic Local Variable

Problem 2: Write a program using an automatic local variable.

Input: One integer.

Output: Print the local value after adding 10.

3. Purpose of register

Problem 3: Explain the purpose of register using a runnable program.

Input: No input.

Output: Print a concise explanation.

4. register Loop Counter

Problem 4: Write a program containing a register loop counter and calculate the sum from 1 to n.

Input: One positive integer n.

Output: Print the sum from 1 through n.

5. Why register is Not Guaranteed

Problem 5: Explain why register does not guarantee CPU-register allocation.

Input: No input.

Output: Print the explanation.

6. Static Local Variable

Problem 6: Write a function using a static local variable and call it three times.

Input: No input.

Output: Print 1 2 3.

7. Count Function Calls with static

Problem 7: Count how many times a function is called using a static local variable.

Input: One integer n indicating the number of calls.

Output: Print the final call count.

8. Automatic Local vs Static Local

Problem 8: Demonstrate the difference between an automatic local variable and a static local variable across two function calls.

Input: No input.

Output: Print auto and static values for two calls.

9. File-Scope static Variable

Problem 9: Create a file-scope static variable and use it from a function in the same source file.

Input: One integer.

Output: Print the static file-scope variable after adding the input.

10. Internal Linkage

Problem 10: Explain internal linkage with a file-scope static name.

Input: No input.

Output: Print the explanation.

11. Purpose of extern

Problem 11: Explain the purpose of extern with a runnable declaration and definition in one translation unit.

Input: No input.

Output: Print the shared value.

12. Share a Global Variable with extern

Problem 12: Model two C files that share a global variable using extern. The runnable solution combines the declarations into one translation unit while preserving the declaration/definition relationship.

Input: One integer to add to the shared value.

Output: Print the updated shared value.

13. Scope vs Lifetime

Problem 13: Explain the difference between scope and lifetime.

Input: No input.

Output: Print two concise lines.

14. Predict a Static Counter

Problem 14: Predict the output of a program containing a static counter function, then verify it.

Input: No input.

Output: Print 2 4 6 from three calls that add 2 each time.

15. Automatic or Static Storage Duration

Problem 15: Identify whether representative objects have automatic or static storage duration.

Input: No input.

Output: Print classifications for local, static local and file-scope global objects.

16. Why Uninitialized automatic Values are Unsafe

Problem 16: Explain why reading an uninitialized automatic variable is unsafe. Do not execute an indeterminate read.

Input: No input.

Output: Print the explanation.

17. static Global vs static Local

Problem 17: Explain the difference between static global and static local declarations.

Input: No input.

Output: Print scope/linkage/storage-duration differences.

18. Header extern Declaration

Problem 18: Model a header file containing an extern declaration and use it from another C file. The runnable version keeps the pieces together.

Input: No input.

Output: Print the shared configuration value.

19. static Helper Function

Problem 19: Create a static helper function that has internal linkage and use it inside the same source file.

Input: One integer.

Output: Print the square of the integer.

20. Mini Project with auto, register, static and extern

Problem 20: Create a small runnable program demonstrating auto, register, static and extern. A real multi-file project would place the extern declaration and definition in separate files.

Input: One positive integer n.

Output: Print the sum 1..n, the static call count, and the shared extern-backed global value.

22.18 Interview Questions

1. What is a storage class?
2. What is the difference between scope and lifetime?
3. Why is static local useful?
4. What is internal linkage?
5. What is external linkage?
6. Does register guarantee register storage?
7. What is the purpose of extern?
8. What is the difference between a declaration and a definition?
9. What happens to a static local variable after a function returns?
10. Why might static be used for a helper function?

22.19 Key Takeaway

๐ŸŽฏ Remember:

auto โ†’ ordinary local variable.

register โ†’ optimization request.

static local โ†’ remembers its value.

static file-scope โ†’ private to the translation unit.

extern โ†’ refers to an entity with linkage defined elsewhere.

Scope tells you WHERE a name can be used.

Lifetime tells you HOW LONG the object exists.

Linkage tells you whether declarations can refer to the same entity.
PLACEMENT TIPS

๐Ÿ’ก Storage Classes โ€” Placement Tips

  • Separate the ideas of scope, storage duration, and linkage; interview questions often test the difference.
  • A static local variable has block scope but static storage duration, so it preserves state between calls.
  • A file-scope static name has internal linkage and is commonly used to keep implementation details private to one source file.
  • An extern declaration does not automatically create a second object; normally one translation unit contains the definition.
  • Do not depend on register for optimization. Modern compilers decide register allocation themselves.
  • Never read an uninitialized automatic object. Static-duration objects, by contrast, receive zero initialization when no explicit initializer is supplied.
EXTRA PRACTICE

โœ๏ธ Storage Classes โ€” Extra Practice Questions

  1. Create two counters: one automatic local and one static local, and compare their values across five calls.
  2. Design a module with a file-scope static variable and public getter/setter functions.
  3. Create a two-file example where one file defines a global object and another accesses it through extern.
  4. Compare a file-scope static helper function with a non-static helper function in terms of linkage.
  5. Classify ten declarations by scope, storage duration, and linkage.
  6. Create a small configuration module with a header declaration, one global definition, and internal static helper data.
โ† Previous Topic: Operator Precedence & Associativity Next Topic: Advanced Preprocessor โ†’