In this tutorial, we are going to learn about different storage classes, scope and lifetime of variables.

Scope of Variables in C

In C language, each variable has a storage class which decides scope and lifetime of that variable. The storage class of a variable determines whether the variable has a global or local scope and lifetime or A Storage Class defines the scope (visibility) and life-time of variables and/or functions within a ‘C‘ program.

All variables defined in a C program are allocated some physical location in memory where the variable’s value is stored. Memory and CPU registers are examples of memory locations where a variable’s value can be stored.

Storage Classes:

Storage classes provide the following information:

  • Where the variable would be stored.
  • What will be the initial value of the variable; i.e., the default value for the variable.
  • What is the scope of the variable; i.e., if the variable is accessible globally or is local to a function.
  • What is the life of the variable; i.e., how long would the variable exist in memory.
  • A keyword which specifies the storage class(auto, register, extern and static).

The scope determines the parts of a program in which a variable is available for use.

The lifetime refers to the period during which a variable retains a given value during execution of the program. It is also referred to as longevity.

There are four storage class specifiers in C language, they are:

  • auto
  • extern
  • static
  • register

The general form of a variable declaration that uses a storage class is:

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:

  • Variables declared inside a function are taken to be auto.
  • Variables declared outside a function are taken to be global.

Automatic Variables:

Automatic variables are declared inside a block/function in which they are to be utilized.

These variables are created when a function is called and destroyed automatically when a function is exited.

Automatic variables are private to the function where they are declared. Because of this property, automatic variables are also referred to as local or internal variables.

A variable declared inside a function without any storage class specification is by default an automatic variable.

Auto variables can be only accessed within the block/function they have been declared and not outside them.

We seldom use the auto keyword in declarations because all block-scoped variables which are not explicitly declared with other storage classes are implicitly auto.

The format for specifying the automatic variables are:

auto data_type variable_1, variable_2,..., variable_n;

Some of the important points regarding auto variables are:

        Storage:	        CPU memory
	Initial value:	        undefined (can be any value)
	Keyword:		auto
	Scope:			local to the block in which it is defined
	Lifetime:		till control remains within the block in which 
                                it is defined

Consider the following code:

#include <stdio.h>
void main( ) {
  auto int i = 9;
  {
    auto int i = 99;
    {
      auto int i = 999;
      printf("Third inner block value = %d\n", i);
    }
    printf("Second inner block value = %d\n", i);
  }
  printf("First block value = %d\n", i);
}

Output:

Third inner block value = 999
Second inner block value = 99
First block value = 9

In the above code, you can see three definitions for variable i. Here, there will be no error and the program will compile and execute successfully.

When the code executes, first the printf in the innermost block will print 999 and the variable i defined in the innermost block will no longer be visible as soon as control exits from the block.

Later, the control enters into the second outer block and prints 99 and later the control enters into the outermost block and prints 9.

Note: automatic variables must always be initialized properly, otherwise you are likely to get unexpected results because automatic variables are not given an initial value by default.

External Variables:

Variables that are declared outside a function are by default global variables. Unlike the local variables, global variables are visible in all functions in that program. Any function can use and also change its value.

Let us consider the below example:

void main() {
  int y = 4;
  y = y + x; // Compiler flags this as an error
  ...
}
int x = 5;
void function1() {
  x = x + 10;
  printf ("%d", x);
}

Even though the variable declaration int x; outside the main() function is a valid global declaration, since the compiler scans from the top of the file, when it reaches the statement y = y + x;, it raises an error saying the variable x is not declared before its usage.

One solution is to move the declaration int x; above the main() function. The second solution is to declare the variable before it is used inside the main method with the keyword extern, as extern int x;.

The extern keyword used before the variable informs the compiler that this variable is declared somewhere else globally and that it has to refer to it. The extern declaration does not allocate storage space for variables because it is only trying to refer to the already declared global variable.

For this reason, we cannot initialize the variable in the extern declaration. A normal global variable can be made extern when it is being used much before its declaration.

The format for specifying the external variables is

extern data_type variable_1, variable_2,..., variable_n;

Some of the important points regarding extern variables are:

	Storage:		Memory
	Initial value:	        zero (0)
	Keyword:		extern
	Scope:			entire program
	Lifetime:		throughout the program execution

 Register Variables:

Auto variables are stored in memory. CPU also has a small storage area called registers which are used for quick storage and retrieval. In C, we can suggest the compiler store certain variables in the CPU registers by specifying them with the storage class register. Apart from their physical storage location, register variables follow the same rules of scope as automatic variables.

The syntax for declaring register variables is

register data_type variable_1;

There may be some special cases when we want some frequently accessed variables to be stored in registers to increase the performance of the program. In such cases, we use the register storage class while declaring the variable.

It should be noted that there is no guarantee that these variables will always be stored in registers. When there isn’t enough space in registers, they will be stored in the memory along with other auto variables.

Care should be taken that we do not specify too many variables as register variables, as it may even degrade the performance. If there are too many, the CPU might end up spending too much time moving data back and forth between registers and temporary storage area, if there are not enough registers to hold all such variables.

Ideally, registers should be used only when one has good knowledge of the compiler and computer architecture being used.

A few points regarding register variables are given below:

	Storage:		CPU registers
	Initial value:	        garbage value
	Keyword:		register
	Scope:			local to the block in which it is defined
	Lifetime:		till control remains within the block in which
                                it is defined

 Static Variables:

A variable can be declared as a static variable by using the keyword static. Auto variables are created each time they are initialized in a block and are destroyed when they go out of scope. However, static variables are initialized only once and they remain in existence till the end of the program.
A static variable can either be local (to a function) or global. The format for specifying static variables is

static data_type variable_1, variable_2,..., variable_n;

The static variables which are declared inside a function are stored in the statically allocated memory and remain alive throughout the execution of the program, but remember that their scope remains local to the function. The main difference between auto and static is that the static variables do not disappear when the function is no longer active (in scope) and their values persist across multiple calls of the same function.

Some of the important points regarding static variables are:

	Storage:		Memory
	Initial value:	        zero (0)
	Keyword:		static
	Scope:			local to the block in which it is defined
	Lifetime:		throughout the program execution

REFERENCES:

Happy Learning 🙂