๐พ 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.
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.
registerexpresses 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 |
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.
The region of program text in which an identifier can be used to refer to the declared entity.
Describes how long the storage associated with an object exists.
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.
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; } 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:
- At block scope, it gives the object static storage duration.
- At file scope, it gives an object or function internal linkage.
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.
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.
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; } 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
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_valuehas static storage duration and external linkage.private_valuehas static storage duration and internal linkage.local_valuehas automatic storage duration.persistent_valuehas 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
staticalways means global. - Thinking
staticmeans constant. - Thinking
registerguarantees a CPU register. - Thinking
autoinitializes local variables to zero. - Thinking
externcreates 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.
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
staticlocals deliberately when state should survive calls but remain encapsulated. - Use file-scope
staticto keep implementation details private to a source file. - Use headers for declarations and source files for definitions where appropriate.
- Use
externfor declarations of externally linked entities rather than duplicating definitions. - Do not depend on
registerfor performance. - Do not describe storage classes solely as physical memory locations.
22.15 Quick Revision
๐ 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.
๐ฌ Storage Classes โ Scope, Lifetime & Linkage
Compare the key idea behind auto, register,
static, and extern.
๐ฌ Storage Class Visualizer
๐ 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.
Ordinary block-scope local variables have automatic storage duration by default.
A static local object has static storage duration, so the same object persists across calls.
extern is commonly used to declare an object or function whose definition is provided elsewhere.
A file-scope function declared static has internal linkage.
Objects with static storage duration are zero-initialized before program startup if no explicit initializer is provided.
register is only a request/hint; the implementation decides actual register allocation.
A static local is visible only within its block but exists for the whole program execution.
Lifetime describes the period during program execution in which an object exists.
At file scope, static gives internal linkage to object and function names.
A declaration such as extern int count; can refer to a definition elsewhere without defining a second object.
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.
Problem 1: Explain the purpose of the auto storage class using a runnable program.
Input: No input.
Output: Print a concise explanation.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
printf("auto: block-scope local object with automatic storage duration");
return 0;
}
Problem 2: Write a program using an automatic local variable.
Input: One integer.
Output: Print the local value after adding 10.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
auto int value;
scanf("%d", &value);
value += 10;
printf("%d", value);
return 0;
}
Problem 3: Explain the purpose of register using a runnable program.
Input: No input.
Output: Print a concise explanation.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
printf("register: local variable hint; actual register use is implementation-controlled");
return 0;
}
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.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
int n;
int sum = 0;
register int i;
scanf("%d", &n);
for (i = 1; i <= n; i++)
sum += i;
printf("%d", sum);
return 0;
}
Problem 5: Explain why register does not guarantee CPU-register allocation.
Input: No input.
Output: Print the explanation.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
printf("register is a language hint; the implementation decides actual storage");
return 0;
}
Problem 6: Write a function using a static local variable and call it three times.
Input: No input.
Output: Print 1 2 3.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
void show(void)
{
static int count = 0;
count++;
printf("%d", count);
}
int main()
{
show(); printf(" ");
show(); printf(" ");
show();
return 0;
}
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.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int callCounter(void)
{
static int count = 0;
return ++count;
}
int main()
{
int n;
int result = 0;
scanf("%d", &n);
for (int i = 0; i < n; i++)
result = callCounter();
printf("%d", result);
return 0;
}
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.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
void show(void)
{
int automatic = 0;
static int persistent = 0;
automatic++;
persistent++;
printf("%d %d\n", automatic, persistent);
}
int main()
{
show();
show();
return 0;
}
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.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
static int total = 10;
int main()
{
int x;
scanf("%d", &x);
total += x;
printf("%d", total);
return 0;
}
Problem 10: Explain internal linkage with a file-scope static name.
Input: No input.
Output: Print the explanation.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
printf("internal linkage: the file-scope name is confined to its translation unit");
return 0;
}
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.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
extern int shared;
int shared = 25;
int main()
{
printf("%d", shared);
return 0;
}
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.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
/* file1.c concept: definition */
int shared = 100;
/* file2.c concept: declaration */
extern int shared;
int main()
{
int x;
scanf("%d", &x);
shared += x;
printf("%d", shared);
return 0;
}
Problem 13: Explain the difference between scope and lifetime.
Input: No input.
Output: Print two concise lines.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
printf("Scope: where a name can be used.\n");
printf("Lifetime: how long an object exists.");
return 0;
}
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.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int nextValue(void)
{
static int value = 0;
value += 2;
return value;
}
int main()
{
int a = nextValue();
int b = nextValue();
int c = nextValue();
printf("%d %d %d", a, b, c);
return 0;
}
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.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
printf("ordinary local: automatic\n");
printf("static local: static\n");
printf("file-scope object: static");
return 0;
}
Problem 16: Explain why reading an uninitialized automatic variable is unsafe. Do not execute an indeterminate read.
Input: No input.
Output: Print the explanation.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
printf("Do not read an uninitialized automatic object; initialize it before use.");
return 0;
}
Problem 17: Explain the difference between static global and static local declarations.
Input: No input.
Output: Print scope/linkage/storage-duration differences.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
printf("static local: block scope, static storage duration.\n");
printf("static file-scope: file scope, static storage duration, internal linkage.");
return 0;
}
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.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
/* config.h concept */
extern int config;
/* config.c concept */
int config = 42;
/* main.c concept */
int main()
{
printf("%d", config);
return 0;
}
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.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
static int square(int x)
{
return x * x;
}
int main()
{
int x;
scanf("%d", &x);
printf("%d", square(x));
return 0;
}
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.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
/* Shared-object concept */
extern int shared;
int shared = 10;
int calls(void)
{
static int count = 0;
return ++count;
}
int main()
{
auto int n;
register int i;
int sum = 0;
scanf("%d", &n);
for (i = 1; i <= n; i++)
sum += i;
int callCount = calls();
shared += sum;
printf("sum=%d calls=%d shared=%d", sum, callCount, shared);
return 0;
}
22.18 Interview Questions
22.19 Key Takeaway
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.
๐ก 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
staticname has internal linkage and is commonly used to keep implementation details private to one source file. - An
externdeclaration does not automatically create a second object; normally one translation unit contains the definition. - Do not depend on
registerfor 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.
โ๏ธ Storage Classes โ Extra Practice Questions
- Create two counters: one automatic local and one static local, and compare their values across five calls.
- Design a module with a file-scope static variable and public getter/setter functions.
- Create a two-file example where one file defines a global object and another accesses it through
extern. - Compare a file-scope static helper function with a non-static helper function in terms of linkage.
- Classify ten declarations by scope, storage duration, and linkage.
- Create a small configuration module with a header declaration, one global definition, and internal static helper data.