Storage classes in C help define the scope, lifetime, visibility, and storage-related properties of variables and functions. They tell the compiler how a variable can be accessed and how long its stored value is maintained.
auto, register, static, and
extern.
A storage class specifies certain properties of a variable, such as its scope and lifetime.
int number = 10;
Variables can have different storage characteristics depending on where and how they are declared.
The commonly studied storage-class specifiers are:
autoregisterstaticexternEach one has a different purpose and behavior.
Two important concepts when studying storage classes are scope and lifetime.
Storage-class specifiers help determine these properties.
The auto storage-class specifier is associated with local
variables declared inside a block.
int main()
{
auto int number = 10;
printf("%d", number);
return 0;
}
The variable exists during execution of the block in which it is declared.
For ordinary local variables, the auto keyword is normally
not written explicitly.
int main()
{
int number = 10;
printf("%d", number);
return 0;
}
The declaration above is an ordinary automatic local variable.
void display()
{
auto int value = 50;
printf("%d", value);
}
int main()
{
display();
return 0;
}
The variable value is local to the function and its lifetime
is associated with execution of that function invocation.
The register specifier requests that a variable be stored in
a processor register when practical.
int main()
{
register int count = 10;
printf("%d", count);
return 0;
}
The compiler decides whether the request can actually be honored.
Register storage can be useful for variables that are accessed frequently, but modern compilers generally make their own optimization decisions.
register int counter;
for (counter = 0; counter < 10; counter++)
{
printf("%d ", counter);
}
The register keyword should not be treated as a guarantee
that the variable will be stored in a CPU register.
A program should not use the address-of operator & on
an object declared with the register storage-class
specifier.
register int number = 10;
/* &number is not allowed */
This is one reason register differs from an ordinary local
variable declaration.
The static specifier can be used with variables at block
scope or file scope.
void display()
{
static int count = 0;
count++;
printf("%d\n", count);
}
A static local variable retains its stored value between function calls.
#include <stdio.h>
void counter()
{
static int count = 0;
count++;
printf("%d\n", count);
}
int main()
{
counter();
counter();
counter();
return 0;
}
Output:
1
2
3
The variable retains its value between calls.
A static local variable is useful when a function needs to remember information between calls without exposing that variable outside the function.
void visits()
{
static int count = 0;
count++;
printf("Function called %d times\n", count);
}
void test()
{
static int number = 10;
printf("%d\n", number);
number++;
}
The initialization of the static local variable occurs once. Later calls continue using its existing stored value.
At file scope, a variable declared with static has internal
linkage. This means its name is limited to the current source file.
static int total = 100;
Other source files cannot refer to this file-scope variable using the same external name.
A static object's lifetime lasts for the entire execution of the program, even when the variable is declared inside a function.
void display()
{
static int number = 5;
number++;
printf("%d\n", number);
}
The variable remains available for future calls to the function.
The extern keyword is commonly used to declare an object
that is defined elsewhere, often in another source file.
extern int total;
This declaration tells the compiler that the definition of
total is provided elsewhere.
#include <stdio.h>
int total = 100;
void display()
{
extern int total;
printf("%d", total);
}
int main()
{
display();
return 0;
}
The extern declaration refers to the existing definition of
total.
Suppose one source file contains the definition:
int total = 500;
Another source file can declare it with:
extern int total;
When the program is linked, both source files can refer to the same object, provided the definition is available to the program.
| static | extern |
|---|---|
| Can give a file-scope object internal linkage. | Can declare an object defined elsewhere. |
| Static local variables retain their values between calls. | Commonly used to refer to an externally defined object. |
| Can limit a file-scope name to one source file. | Can allow a declaration to refer to an external definition. |
void test()
{
int number = 10;
printf("%d", number);
}
The variable number can be accessed only within its block.
It cannot be directly accessed from another function.
void test()
{
int number = 10;
printf("%d", number);
}
For an ordinary local automatic variable, the object's lifetime is tied to execution of the block in which it is declared.
Automatic local variable:
void test()
{
int count = 0;
count++;
printf("%d\n", count);
}
Calling this function repeatedly starts count from its
initial value for each invocation.
Static local variable:
void test()
{
static int count = 0;
count++;
printf("%d\n", count);
}
The static variable retains its value between calls.
Objects with static storage duration that are not explicitly initialized are initialized to zero.
void test()
{
static int number;
printf("%d", number);
}
The value of number starts as 0.
static when a local variable needs to retain its value between calls.static when a file-level object should have internal linkage.extern when referring to an object defined elsewhere.register only when appropriate; modern compilers usually handle optimization themselves.#include <stdio.h>
void counter()
{
static int count = 0;
count++;
printf("Count = %d\n", count);
}
int main()
{
counter();
counter();
counter();
counter();
return 0;
}
Output:
Count = 1
Count = 2
Count = 3
Count = 4
register guarantees CPU-register storage.extern without providing a corresponding definition where required.static variables can be accessed from another source file.| Specifier | Common Use | Important Property |
|---|---|---|
auto |
Local variables | Automatic storage duration |
register |
Local variables | Requests register storage |
static |
Local/file-scope objects | Retains lifetime; file-scope static gives internal linkage |
extern |
External declarations | Refers to an object defined elsewhere |
#include <stdio.h>
void visit()
{
static int count = 0;
count++;
printf("Function called %d times\n", count);
}
int main()
{
visit();
visit();
visit();
return 0;
}
The static variable remembers its previous value every time the function is called.
Storage-class concepts also apply to functions. For example, a function
defined with static at file scope has internal linkage and
can be called only from that source file.
static void display()
{
printf("Hello");
}
This is useful when a helper function should remain private to one source file.
Practice the following programs:
auto is associated with ordinary local automatic variables.register requests register storage but does not guarantee it.static local variables retain their values between function calls.static gives internal linkage.extern is commonly used to declare an object defined elsewhere.Question: Which storage-class specifier allows a local variable to retain its value between function calls?