Storage Classes in C

Storage Classes in C from C compiler’s point of view, a variable name identifies some physical location within the computer where the string of bits representing the variable’s value is stored. There are basically two kinds of locations in a computer where such a value may be kept— Memory and CPU registers. It is the variable’s storage class that determines in which of these two locations the value is stored.

Table of contents [ Hide ]

Moreover, a variable’s storage class tells us:

  • Where the variable would be stored
  • What will be the initial value of the variable, if initial value is not specifically assigned.(i.e. the default initial value)
  • What is the scope of the variable; i.e. in which functions the value of the variable would be available
  • What is the life of the variable; i.e. how long would the variable exist.

There are four storage classes in C:

  • Automatic storage class
  • Register storage class
  • Static storage class
  • External storage class

Automatic Storage Class

The features of a variable defined to have an automatic storage class are as under:

StorageMemory
Default initial valueAn unpredictable value, which is often
called a garbage value.
ScopeLocal to the block in which the variable
is defined
LifeTill the control remains within the block
in which the variable is defined.
Automatic Storage Class

Following program shows how an automatic storage class variable is declared, and the fact that if the variable is not initialized it contains a garbage value

main( )
{
auto int i, j ;
printf ( “\n%d %d”, i, j ) ;
}

The output of the above program could be…

1211 221

where, 1211 and 221 are garbage values of i and j. When you run this program you may get different values, since garbage values

are unpredictable. So always make it a point that you initialize the automatic variables properly, otherwise you are likely to get unexpected results. Note that the keyword for this storage class is auto, and not automatic

Scope and life of an automatic variable is illustrated in the following program.

main( ) 
{ 
 auto int i = 1 ; 
 { 
 { 
 { 
 printf ( "\n%d ", i ) ; 
 } 
 printf ( "%d ", i ) ; 
 } 
 printf ( "%d", i ) ; 
 } 
}

The output of the above program is:

1 1 1

This is because, all printf( ) statements occur within the outermost block (a block is all statements enclosed within a pair of braces) in which i has been defined. It means the scope of i is local to the block in which it is defined. The moment the control comes out of the block in which the variable is defined, the variable and its value is irretrievably lost. To catch my point, go through the following program

main( ) 
{ 
 auto int i = 1 ; 
 {
auto int i = 2 ; 
 { 
 auto int i = 3 ; 
 printf ( "\n%d ", i ) ; 
 } 
 printf ( "%d ", i ) ; 
 } 
 printf ( "%d", i ) ; 
}

The output of the above program would be:

3 2 1

Note that the Compiler treats the three i’s as totally different variables, since they are defined in different blocks. Once the control comes out of the innermost block the variable i with value 3 is lost, and hence the i in the second printf( ) refers to i with value 2. Similarly, when the control comes out of the next innermost block, the third printf( ) refers to the i with value 1

Register Storage Class

The features of a variable defined to be of register storage class are as under:

StorageCPU registers
Default initial valueGarbage value.
ScopeLocal to the block in which the variable
is defined
LifeTill the control remains within the block
in which the variable is defined.
Register Storage Class

A value stored in a CPU register can always be accessed faster than the one that is stored in memory. Therefore, if a variable is used at many places in a program it is better to declare its storage class as register. A good example of frequently used variables is loop counters. We can name their storage class as register.

main( ) 
{ 
 register int i ; 
 for ( i = 1 ; i <= 10 ; i++ ) 
 printf ( "\n%d", i ) ; 
} 

Here, even though we have declared the storage class of i as register, we cannot say for sure that the value of i would be stored in a CPU register. Why? Because the number of CPU registers are limited, and they may be busy doing some other task. What happens in such an event… the variable works as if its storage class is auto

Not every type of variable can be stored in a CPU register.

For example, if the microprocessor has 16-bit registers then they cannot hold a float value or a double value, which require 4 and 8 bytes respectively. However, if you use the register storage class for a float or a double variable you won’t get any error messages. All that would happen is the compiler would treat the variables to be of auto storage class.

Static Storage Class

The features of a variable defined to have a static storage class are as under:

StorageMemory
Default initial valueZero
ScopeLocal to the block in which the variable
is defined.
LifeValue of the variable persists between
different function calls.
Static Storage Class

Compare the two programs and their output given in Figure 6.3 to understand the difference between the automatic and static storage classes

main( )
{
increment( ) ;
increment( ) ;
increment( ) ;
}
increment( )
{
auto int i = 1 ;
printf ( “%d\n”, i ) ;
i = i + 1 ;
}
main( )
{
increment( ) ;
increment( ) ;
increment( ) ;
}
increment( )
{
static int i = 1 ;
printf ( “%d\n”, i ) ;
i = i + 1 ;
}
Static Storage Class

The output of the above programs would be:

1
1
1
1
2
3
Static Storage Class

External Storage Class

The features of a variable whose storage class has been defined as external are as follows:

StorageMemory
Default initial valueZero
ScopeGlobal
LifeAs long as the program’s execution
doesn’t come to an end.
External Storage Class

External variables are declared outside all functions, yet are available to all functions that care to use them

Example

int i ; 
main( ) 
{ 
 printf ( "\ni = %d", i ) ; 
 increment( ) ; 
 increment( ) ; 
 decrement( ) ; 
 decrement( ) ; 
} 
increment( ) 
{ 
 i = i + 1 ; 
 printf ( "\non incrementing i = %d", i ) ; 
} 
decrement( ) 
{ 
 i = i - 1 ; 
 printf ( "\non decrementing i = %d", i ) ; 
}

The output would be:
i = 0
on incrementing i = 1
on incrementing i = 2
on decrementing i = 1
on decrementing i = 0

Look at the following program

int x = 21 ; 
main( ) 
{ 
 extern int y ; 
 printf ( "\n%d %d", x, y ) ; 
} 
int y = 31 ;

Note the difference between the following:

extern int y ;
int y = 31 ;

Leave a Comment