Every variable in C is associated with a storage class in addition to its data type and name.
A variable’s storage class specifier tells us :
1. The place where the variable may be stored: Memory or CPU registers.
2. The initial default value of the variable, if the initial value is not specified explicitly in the program,
3. The scope of a variable. It specifies the area or portion of the program where it can access. A local variable’s scope is limited to the function in which it declares, whereas the global variable is visible throughout the program.
Limiting the variable’s scope is very useful when several programmers are working on different pieces of the same program. On limiting the scope of the variables to the block of code in which is declared, there will be no need to worry about conflicting variables of the same name used by others in other parts of the program.
4. The lifetime, i.e. how long the variable stays in memory. The lifetime of a variable is a period during which memory associates with a variable. It is the duration between the creation of the variable and its destruction.
A local variable’s lifetime is when a function is called, in which the variable declares till the end of the execution of that function call. A global variable’s lifetime is the program’s period of execution as it declares outside the function.
Classification of Storage Classes in C
The storage classes in C are classified into two category Automatic storage classes, Static storage classes.
Automatic Storage Class in C
• Automatic storage class variables will be created automatically and destroyed automatically.
• Automatic storage class variables will store in stack area of a data segment or CPU register.
• In automatic storage class, we’ve got two types of storage class specifier, i.e. auto, register.
Static Storage Class
• Static storage class variables will create only once, and during the program, it is going to be there in active mode.
• Static variables are stores in the static area of the data segment.
• In static storage class, we’re having two kinds of storage class specifiers, i.e. static, extern.
Syntax:
storage-specifier data-type variable-name;
Example
int marks;
auto int marks; //Both are Same
Storage Class | Keyword | Mem Location | Default Value | Scope | Lifetime |
Automatic | auto | RAM | Garbage Value | Local | Till the control remains. |
External | extern | RAM | Zero | Global | As long as the program’s execution. |
Static | static | RAM | Zero | Local | The value persists between different function. |
Register | register | CPU | Garbage Value | Local | Till the control remains |
Auto Storage Class
• All local variables, by default, belong to the auto storage class.
• Automatic variables allocate memory automatically at runtime and become freed automatically when the function’s execution is finish.
• The automatic variables’ visibility and scope are limited to the block/function where they are declared, including any blocks nested within that block. For these reasons, they are also called local variables.
• The automatic variables are default initial Value is an arbitrary value, i.e. garbage value.
• The keyword used for defining automatic variables is auto.
• No block outside the block definition can directly access automatic variables (by variable name); however, other blocks or functions can access out of their scope by using pointers.
• For faster access of a variable, it’s better to choose register specifiers instead of auto specifiers.
• Register variables store in register memory whereas auto variables store in primary CPU memory.
• Only a few variables can save in register memory. Thus, we can use variables as a register which are used quite frequently in a C program.
You can declare auto variable within a block by prefixing its declaration with auto storage class specifier. For example,
auto int x;
declares x to be auto variable of type int. The keyword auto is optional and seldom used because it is the default storage class, specifier.
auto variables not initialized (i.e. contains garbage value) unless you explicitly do so. It can initialize with constant or expression consisting of constant or previously defined initialized variables.
For instance,
auto int x; /*Initialized with garbage value*/ auto int y = 1; /*Initialized with 1*/ auto int z = y + 5; /*Initialized with 6 as y = 1*/
It should note that automatic variables declared with initializers initialized every time the block they declared is entered or accessed.
Examples auto Storage Class
#include<stdio.h> int main() { int Marks; char Name; float Percentage; printf("%d %c %f",Marks,Name,Percentage); return 0; }
Output:
The following C program demonstrates the visibility level of auto variables.
#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:
From the above example program, you see three definitions for variable i. Here, you could be wondering if there might be more than one variable with the same name. Yes, there might be if these variables define in various blocks. So, there’ll be no mistake here, and the application will compile and execute successfully.
The printf in the innermost block will print 3, and also the variable i defined at the innermost block becomes destroyed whenever control exits in the block. Now control comes to the next outer block and prints 2 subsequently comes into the outer block and prints 1.
• The variables declared within a block with no storage class specification could be considered an automatic storage class.
• These variables can also be called as local variables since they get destroyed after the implementation of the block.
• As the variables made automatically, garbage values assigned by the compiler.
extern Storage Class
The ‘extern’ variables can also be Known as global variables. The global variables can be accessed by all the functions that follow their definition in a source file. These variables can use to share information in a program that expands across multiple files. If a global variable defined in some file and you want to use this variable in some other file in your multifile program, then declare such variable as an extern variable (which stands for external) using the keyword extern as follows,
extern int var;
The extern declaration statement informs the compiler that a global variable of a given name and type already exists and can now use in the file. It does not create the variable or reserve storage for the variables. The actual storage allocates when that variable defines as a global variable. A global variable declaration does not use the extern keyword. One should note that there must only be one definition of an external variable among all the files that make up the source program. Other files contain extern declarations to access it. An external variable can thus be defined only once but declared many times using the extern keyword. The ‘extern’ modifier can be used when a couple of files are sharing the same global variables or functions. When a global variable is not initialized explicitly, it is initialized to 0. Initialization is an extern declaration not allowed and causes a compilation error.
In the next example, the extern specifier tells the compiler that variable ext has defined and it’s declared here for compiler’s information.
#include<stdio.h> extern int ext; int main() { printf("ext: %d\n", ext); } int ext = 5;
If you alter the statement extern int ext; to extern int ext = 10; you may again get an error “Redefinition of ‘ext'” as with extern specifier the variable cannot initialize, if it’s defined elsewhere. Otherwise, then the extern declaration becomes a definition.
Static Storage Class
C also provides the facility to declare static variables. As the name indicates, the static variables retain their value as long as the program executes. You can declare a static variable by using the static storage class access specifier. For example,
static int i = 1;
Static variables can be of two types depending on the placement of the declaration.
• Static variables with block scope.
• Static variables with file scope.
Static variables with block scope are those who declare inside a function. The scope of these types of static variables is the same as that of auto variables, i.e. they are accessible only within the function. They are declared and cannot access from outside. However, unlike auto to variables, they are not created and destroyed each time the function they declare is called, rather they are created once, and they retain their value throughout the program’s life. The last value store in the variable when the function exited available to the function the next time it calls. Also, static variables can initialize with constants or constant expression. If not initialized, by default, they initialize to 0. Static variables frequently used in situations in which you want to retain information between function calls, such as the number of times the function called etc.
The following code defines static variable i at two locations in two blocks within the function. During second call static variables retain their old values, and they aren’t initialized again at the next call.
#include<stdio.h> void staticStorage() { static int i; { static int i = 1; printf("%d ", i); i++; } printf("%d\n", i); i++; } int main() { staticStorage(); staticStorage(); }
When static specifier applies to a global variable, then compiler creates that variable known only to the file where it described. A static global variable comes with an internal linkage that means even although the variable is global; routines in different files don’t have any understanding of it and can’t access and change its contents directly. This C program defines a single static global variable SVar, and a static function staticStorage(), both the function and variable are described static they can’t use outside the file.
#include<stdio.h> static int SVar = 1; static void staticvar() { static int i; printf("%d ", i); i++; printf("%d\n", SVar); SVar++; } int main() { staticvar(); staticvar(); }
Static variables have default initial value zero and initialized only once in their lifetime.
Register Storage Class
Registers are special storage areas within a computer’s CPU. The actual arithmetic and logic operations that comprise a program carried out within these registers. Usually, these operations are carried out by transferring information from the computer’s memory to these registers, carrying out the indicated operations, and transferring the results back to the computer’s memory. This procedure is repeated many times during the program’s execution.
• C also permits to declare a variable using a register storage class specifier.
• The variables stored in the register storage class are similar to the automatic storage class in C.
• When the register specifier applies to a variable, then the variable’s value is stored in the CPU register rather than in memory, where normal variables are stored.
• The scope and lifetime of register variables are the same as those of auto variables, i.e. a register variable is created when the function declares it is entered and destroyed when the function finishes execution. Since registers are in the CPU, so the operation performed on the register variable would occur much faster than a normal variable. Also, computer instructions referring to registers generally require lesser space than instructions referring to memory locations.
• We can’t dereference the register variables, i.e., we can’t use the unary ‘&’ operator for the register variable.
• The register variables’ access time is faster compared to that of the variables stored in the memory.
• The initial default value of the register local variables is 0.
• The keyword used to specify the variable is register. It’s the compiler’s choice if or not; the variables can store in the register.
• Obtaining the address of register variables is tough.
• Static variables can’t store in the register because we can’t save more specifiers to the identical variable.
• Variables belonging to the register storage class are local to the block.
You can declare the register variable within a block by prefixing its declaration with the register storage class specifier. For instance,
register int x;
declares x to be a register variable of type int.
When the program containing the register variable executes, it is the compiler’s responsibility to allocate the register to the register variable. If no register is available, C will automatically convert register variables into non-register variables when the compiler encounters a register variable declaration. One should remember that as register variables are not stored in memory, it is illegal to use the address operator to determine the register variable’s address.
register storage class specifier is best suited for variables that are accessed or updated frequently or whose access time is critical. For example, loop control variables.
The next code is to get the address of variable i to pointer variable pt, but it won’t succeed because i will be declared register; It will not compile and exit with error “error: address of register variable.”
#include<stdio.h> int main() { register int i = 1; int *pt = &i; //error: address of register variable. printf("Value of i: %d", *pt); printf("Address of i: %u", pt); }