Storage class specifiers tells the compiler where to store a variable, how to store a variable, what is the initial value of a variable and life time of a variable. auto specifier static specifier register specifier extern specifier
Storage class in C decides the part of storage to allocate memory for a variable, it also determines the scope of a variable. All variables defined in a C program get some physical location in memory where variable's value is stored.
The storage class of a variable in C determines the life time of the variable if this is global or local. Along with the life time of a variable, storage class also determines variable's storage location, the of the variable, and the initial value of the variable.
There are 4 types of storage class specifiers
The auto specifier indicates that the memory location of a variable is temporary. In other words, a variable's reserved space in the memory can be erased or relocated when the variable is out of its scope.
A variable declared inside a function without any storage class specification, is by default an automatic variable. They are created when a function is called and are destroyed automatically when the function's execution is completed. Automatic variables can also be called local variables because they are local to a function. By default they are assigned garbage value by the compiler.
Example of auto Specifier
#include <stdio.h>
int main( )
{
auto int i = 1;
{
auto int i = 2;
{
auto int i = 3;
printf ( "\n%d ", i);
}
printf ( "%d ", i);
}
printf( "%d\n", i);
}
Output
3 2 1
A variable with program scope is visible through all source files that make up an executable program. A variable with program scope is also called a global variable.
The extern storage class is used to give a reference of a global variable that is visible to ALL the program files. When extern specifier is used with a variable declaration then no storage is allocated to that variable and it is assumed that the variable has already been defined elsewhere in the program. When we use extern specifier the variable cannot be initialized because with extern specifier variable is declared, not defined.
Suppose we have two global int variables, y and z, that are defined in one file, and then, in another file, we may have the following declarations:
int x = 0; /* a global variable */
extern int y; /* an allusion to a global variable y */
int main()
{
extern int z; /* an allusion to a global variable z */
int i; /* a local variable */
.
.
.
return 0;
}
Example of extern Storage Specifiers
#include<stdio.h>
int x = 10 ;
int main( )
{
extern int y;
printf("The value of x is %d \n",x);
printf("The value of y is %d",y);
return 0;
}
int y=50;
Output
The value of x is 10
The value of y is 50
The static specifier, can be applied to variables with either block scope or program scope. When a variable within a function is declared with the static specifier, the variable has a permanent duration. In other words, the memory storage allocated for the variable is not destroyed when the scope of the variable is exited, the value of the variable is maintained outside the scope, and if execution ever returns to the scope of the variable, the last value stored in the variable is still there.
Example static Storage Specifier
#include <stdio.h>
/* function declaration */
void func(void);
static int count = 5; /* global variable */
main() {
while(count--) {
func();
}
return 0;
}
/* function definition */
void func( void ) {
static int i = 5; /* local static variable */
i++;
printf("i is %d and count is %d\n", i, count);
}
Output
i is 6 and count is 4
i is 7 and count is 3
i is 8 and count is 2
i is 9 and count is 1
i is 10 and count is 0
The word register is borrowed from the world of computer hardware. Each computer has a certain number of registers to hold data and perform arithmetic or logical calculations. Because registers are located within the CPU (central processing unit) chip, it's much quicker to access a register than a memory location. Therefore, storing variables in registers may help to speed up program.
The register specifier only gives the compiler a suggestion. In other words, a variable specified by the register keyword is not guaranteed to be stored in a register. The compiler can ignore the suggestion if there is no register available, or if some other restrictions have to apply.
Variables belonging to register storage class are local to the block which they are defined in, and get destroyed on exit from the block.
If a variable is declared register, the unary & (address of) operator may not be applied to it, explicitly or implicitly because the variable is intended to be stored in a register, not in the memory.
Only limited variables can be used as register since register size is very low. (16 bits, 32 bits or 64 bits)
Example of register Storage Specifier
int main()
{
/* block scope with the register specifier */
register int i;
. . .
for (i=0; i<MAX_NUM; i++){
/* some statements */
}
. . .
return 0;
}
Summary of Storage Class Specifiers
Storage Specifier | Storage place | Initial/default value | Scope | Life |
---|---|---|---|---|
auto | CPU Memory | Garbage value | local | Within the function only |
extern | CPU Memory | Zero | Global | Till the end of the main program. Variable definition might be anywhere in program |
static | CPU Memory | Zero | local | Retains the value of the variable between different function calls. |
register | Register memory | Garbage value | local | Within the function only |