×
☰ Menu

C Storage Classes and Storage Class Specifiers

 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 are given a specific physical location in memory to hold their values. The types of memory locations where a variable's value can be kept include memory and CPU registers. The storage class of a variable in C determines the lifetime of the variable if this is 'global' or 'local'. Along with the lifetime of a variable, storage class also determines the variable's storage location (memory or registers), the scope (visibility level) of the variable, and the initial value of the variable.

In C programming there are four storage classes in C those are automatic, register, static, and external.

 storage_class_specifier data_type variable name;

At most one storage class specifier may be given in a declaration. If no storage class specifier is specified then the following rules are used:

  1. Variables declared inside a function are taken to be auto.
  2. Functions declared within a function are taken to be extern.
  3. Variables and functions declared outside a function are taken to be static, with external linkage.

Variables and functions having external linkage are available to all files that constitute a program. File scope variables and functions declared as static (described shortly) have internal linkage. These are known only within the file in which they are declared. Local variables have no linkage and are therefore known only within their own block.

Types of Storage Classes

There are four storage classes in C they are as follows:

  • Automatic Storage Class
  • Register Storage Class
  • Static Storage Class
  • External Storage Class

Now, let us discuss these storage classes one by one.

 

Automatic Storage Class

The automatic storage class includes variables defined within functions or blocks with the auto specifier. If no storage class is specified, all variables defined within a function or block by default belong to automatic storage class. Automatic storage class variables are exclusive to the block in which they are defined and are removed upon block exit.

The following C program demonstrates the visibility level of auto variables.

#include <stdio.h>
int main()
{
auto int j = 1;
{
auto int j = 2;
{
auto int j = 3;
printf ( "\n%d ",j);
}
printf ( "%d ", j);
}
printf( "%d\n", j);
}

Ouput:

3 2 1

--------------------------------
Process exited after 2.077 seconds with return value 0
Press any key to continue . . .

 

You can see three definitions for variable j in the sample program above. You could query if there could be more than one variable with the same name in this situation. Yes, if these variables are declared in separate blocks, there might be. Therefore, there won't be a mistake here, and the program will successfully compile and run. The innermost block's printf will output 3 and the variable I declared inside will be destroyed as soon as control leaves the block. The second outer block is now under control, and it prints 2, after which the outer block is under control, and it prints 1. Here, it is important to keep in mind that because automatic variables are not given an initial value by the compiler, they must always be initialized correctly.

Register Storage Class

A register storage class variable is declared via the register specifier. The register storage class's variables are exclusive to the block in which they are defined and are destroyed when the block is exited. The equivalent of an auto declaration, a register declaration indicates that the stated variable will be accessed frequently; as a result, they are stored in CPU registers rather than in memory. The constraints are implementation-dependent; only a few variables are really put into registers, and only specific types are permitted. The unary & (address of) operator cannot, however, be applied explicitly or implicitly to a variable that is declared register. The compiler also doesn't assign an initial value to register variables.

 

#include <stdio.h>
int main()
{
  register int j= 10;
  int *ptr = &j; //error: address of register variable requested
  printf("Value of j: %d", *ptr);
  printf("Address of j: %u", ptr);
}

Output: 

Value of j: 10Address of j: 6487572
--------------------------------
Process exited after 2.098 seconds with return value 0
Press any key to continue . . .

 

n the above example gets the address of variable j into the pointer variable ptr but it won't succeed because j is declared register; therefore, the above example won't compile and exit with the error "error: address of register variable requested".

Static Storage Class

The static specifier provides the defined variable's static storage class. Within a function or file, static variables can be used. Static variables, in a contrast to global variables, are hidden within their function or file and retain their values during calls. Local and global variables are affected differently by the static specifier.  See the following flavors of the static specifier. When a static specifier is applied to a local variable inside a function or block, the compiler creates permanent storage for it, much as it creates storage for a global variable but a static local variable remains visible only to the function or block in which it is defined. In simple terms, a static local variable is a local variable that retains its value between function calls.

For example, the following program code defines static variable i at two places in two blocks inside function staticDemo(). Function staticDemo() is called twice within from main function. During the second call, static variables retain their old values and are not initialized again in the second call of staticDemo().

#include <stdio.h>
staticDemo()
{
static int i;
{
static int i = 1;
printf("%d ", i);
i++;
}
printf("%d\n", i);
i++;
}
int main()
{
staticDemo();
staticDemo();
return 0;
}

OUTPUT

1 0
2 1
--------------------------------
Process exited after 3.886 seconds with return value 0
Press any key to continue . . .

 External Storage Class

The extern specifier gives the declared variable external storage class. The principal use of extern is to specify that a variable is declared with external linkage elsewhere in the program. To understand why this is important, it is necessary to understand the difference between a declaration and a definition.

  • A declaration declares the name and type of a variable or function.
  • A definition causes storage to be allocated for the variable or the body of the function to be defined.

The same variable or function may have many declarations, but there can be only one definition for that variable or function. 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.

In the following sample C program if you remove extern int x; you will get an error "Undeclared identifier 'x'" because variable x is defined later than it has been used in printf. In this example, the extern specifier tells the compiler that variable x has already been defined and it is declared here for compiler's information.

#include <stdio.h>
extern int y;
int main()
{
printf("y: %d\n", y);
}
int y = 10;

Output: 

y: 10

--------------------------------
Process exited after 1.046 seconds with return value 0
Press any key to continue . . .

Also, if you change the statement extern int x; to extern int y = 10; you will again get an error "Redefinition of 'y'" because with an extern specifier the variable cannot be initialized if it is defined elsewhere. If not then extern declaration becomes a definition.