Storage Classes in C language – Auto, Register, Static, and Extern
Storage Classes in C Introduction:
We have looked at the Call by value and call by reference in our earlier posts, In today’s article, We are going to look at the Storage Classes in the C programming language.
Storage Classes in C Programming Language:
So far we have declared the variables by specifying the datatype. But variables also have another attribute, which defines a few key characteristics of the variable, That attribute is Storage Class. The Storage class in C decides where the variable will be stored in RAM and how long it will live, What is the scope of the variables, etc. The knowledge of storage is very valuable once we start writing multi-file programs (applications).
The storage class decides the following characteristics of the variable
- Storage Location – Where the variable will be stored ( Stack or Register, etc )?
- Lifetime – How long the variable will live?
- Scope ( Visibility ) – Where will be the variable available to access (use)?
- Default Value or Initial Value – What is the initial value of the variable, if declared without any initial value?
Before going into further details, Here is the syntax of variable declaration with storage class
1 |
storage_class data_type variable_name; |
We have four storage classes in the C Programming language, They are
- auto storage class
- register storage class
- static storage class
- extern storage class
Let’s look at each one of the storage classes in detail.
The auto storage class in C language with Example Programs:
If no storage class is specified, The variables which are defined within the function or code block are called the auto storage class ( Automatic Storage class) variable.
syntax:
auto datatype variable_name;
Now let’s look at the four characteristics of the Automatic storage class variables.
Storage Location:
The automatic storage class variables will be stored in the stack segment of the RAM.
Lifetime:
The auto variables will be created when the function or block started and will be destroyed once the function/block is returned. So Lifetime of the automatic storage class variable is the same as the function.
Scope ( Visibility ):
The scope of the automatic variables is within the function or code block which are declared. The auto variables won’t be visible outside of the function/block that they declared, So we can’t access them from outside of the function/block.
Default Value or Initial Value:
The Default Value of the Automatic variables is Garbage Value or Undefined Value. So it is a good idea to initialize the variables with the appropriate value.
📢So The default storage class of the variables declared within the function or code block is Automatic storage calls.
Here are the properties of the Automatic Storage class variable in C language:
Storage Location | Lifetime | Scope | Default Value |
---|---|---|---|
Stack | Function/Block | Function/block | Garbage/undefined value |
Program to understand Automatic storage class in C Language:
Here is a program with automatic storage class variables.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
/*     Program to demonastrate Automatic storage class in C Language */ #include<stdio.h>  void func1() {     auto int a = 10;     printf("In func1, value of a : %d\n", a); }  int main() {     auto int a = 5;     func1();      // code block or complex statement     {         // This 'a' is only visible in this code block.         auto int a = 20;         printf("In Block, value of a : %d\n", a);     }      // print main() funciton 'a'     printf("In main, value of a : %d\n", a);      return 0; } |
Program Output:
Compile and run the program.
1 2 3 4 5 6 |
$ gcc auto-storage-class.c $ ./a.out In func1, value of a : 10 In Block, value of a : 20 In main, value of a : 5 $ |
Auto Storage class program Explanation:
In the above program, We have created the three automatic variables with the name a. and they are defined in different code blocks so no compilation error.
They are three different automatic variables ( with three different scopes )
- The
func1() scope
- The scope of the automatic variable a is func1, So when we printed the variable a inside of the func1() function, So we got the value 10.
- The variable a life also depends on the func1() life, The a will be created when func1 is created and destroyed once the func1() is returned.
- Code block scope within the
main function
- The variable a ( auto int a = 20;) which is inside of the block will be visible only within the block., So When we printed the value of the variable a from the code block within the main() function, The auto variable inside of block ( auto int a = 20) will shadow the outer main function auto variable( i.e auto int a = 5). So we got the number 20 as the output.
- Once the code block is finished, the auto variable a will be destroyed.
- The
main function scope
- Similarly, When we printed the value of the main function variable a, We got the value 5 ( as auto int a = 5 is visible in the main function scope)
We have properly initialized our automatic variables in the above example, We can try without initializing the variables, We will get the undefined values or garbage values.
As the automatic variables are visible only inside the declared function/block, We can re-use the variable names in other functions/blocks.
Register Storage Class in C Language:
The Register storage class variables can be declared within the Function/block. To create a register variable, use the register keyword like below.
1 |
register datatype variable_name; |
The register variables are very similar to the automatic variables, except the register variables are stored in CPU registers instead of the stack.
Lifetime:
The register variables will be created when the function started and will be destroyed once the function is returned. So Lifetime of the register storage class variable is the same as the function or block they declared.
Scope ( Visibility ):
The scope of the register variables is within the function or code block which are declared.
Default Value or Initial Value:
The Default Value of the register variables is Garbage Value or Undefined Value.
Storage Location:
The register storage class variables will be stored in the CPU registers.
The CPU registers are very close to the CPU core, So they are much faster than the RAM, But they are limited (in Bytes). Accessing the variables stored in CPU registers is very fast compared to accessing it from RAM.
So if there is any variable that is accessed quite frequently, Then we can use the register storage class. ( Loop control variables ) for it.
As specified earlier, The CPU registers are very limited, If the compiler is not able to accommodate the CPU register, Then these register storage class variables will be treated as automatic variables. ( Will be stored in stack segment of RAM )
As we are using the CPU register for register storage class variables, The address of operator (&) won’t work on register variables. So if you try to access the address of the register variable, The compiler will raise an error ( address of register variable ‘i’ requested).
Register Storage class variable Properties in C:
Storage Location | Lifetime | Scope | Default Value |
---|---|---|---|
CPU Registers | Function/Block | Function/block | Garbage/undefined value |
Let’s look at the examples of register storage class variables.
C Program to understand the Register Storage class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/*     Program to demonistrate Register storage class in C Language */ #include<stdio.h> int main() {     register int i;      for(i = 0; i<= 10000000; i++)     {         // do some operation         if(i%100000 == 0)             // printing at every 100k             printf("%d ", i);     }      printf("\n");     return 0; } |
Program Output:
1 2 3 4 |
$ gcc register-storage-class.c $ ./a.out 0 100000 200000 300000 400000 500000 600000 700000 800000 900000 1000000 1100000 1200000 1300000 1400000 1500000 1600000 1700000 1800000 1900000 2000000 2100000 2200000 2300000 2400000 2500000 2600000 2700000 2800000 2900000 3000000 3100000 3200000 3300000 3400000 3500000 3600000 3700000 3800000 3900000 4000000 4100000 4200000 4300000 4400000 4500000 4600000 4700000 4800000 4900000 5000000 5100000 5200000 5300000 5400000 5500000 5600000 5700000 5800000 5900000 6000000 6100000 6200000 6300000 6400000 6500000 6600000 6700000 6800000 6900000 7000000 7100000 7200000 7300000 7400000 7500000 7600000 7700000 7800000 7900000 8000000 8100000 8200000 8300000 8400000 8500000 8600000 8700000 8800000 8900000 9000000 9100000 9200000 9300000 9400000 9500000 9600000 9700000 9800000 9900000 10000000 $ |
If you see the above program, We have created a register storage class variable i. And then we used the i as the for loop counter. We have created a loop that starts from and goes till 10000000. So the variable i will be accessed quite frequently. So the compiler can place the variable i in the CPU register and access it very fastly.
Register storage class with the address of operator (&):
If we change the above program and try to access the address of the register variable i, Then we will get the compilation error – error: address of register variable ‘i’ requested
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/*     Program to demonistrate Register storage class in C Language */ #include<stdio.h> int main() {     register int i;     // try to get address of 'i'     int *p = &i;      // error      printf("\n");     return 0; } |
Program Output:
1 2 3 4 5 6 |
/C/functions$ gcc register-storage-class.c register-storage-class.c: In function ‘main’: register-storage-class.c:17:5: error: address of register variable ‘i’ requested   17 |    int *p = &i;       |    ^~~ /C/functions$ |
Static Storage Class in C Language:
The variables which are declared with the static storage specifier are called static variables. The static storage class can be used for functions or variables.
Syntax:
static datatype variable_name;
The local static variables are stored in the data segment of the RAM. ( The initialized static variables are stored in the data segment ( .bs) and the uninitialized variables are stored in the .bss segment)
There are two types of static variables.
- Local Static variables
- Global static variables (and functions)
Local Static Variables in C Language:
The variables which are declared within the function or block are called local static variables. These variables are only visible inside the declared function, But the local static variable will live throughout the program. This means, Even though the function (where variable declared) is returned, The static variable won’t be destroyed.
Let’s look at the characteristics of Local Static Variable
Storage Location:
The local static variables are stored in the data segment of the RAM. ( The initialized static variables are stored in data segment ( .bs) and the uninitialized variables are stored in .bss segment)
Lifetime:
The Lifetime of static local variables is the same as the program. The static variable is created when the program begins and will live throughout the program and be deallocated when the program is terminated. The local static variable will not be created and destroyed based on the function calls. The local static variable is created only once at the start of the program and will retain it’s value between the function calls.
Scope ( Visibility ):
The scope of the local static variable is function or block where it is declared. So it won’t visible outside of the function/block.
Default Value or Initial Value:
If the static variable is not initialized, Then the default value of the local static variable is Zero. ( All .bss variables will be initialized with zeros during the program startup)
Properties of Local Static Variable in C:
Storage Location | Lifetime | Scope | Default Value |
---|---|---|---|
Data Segment ( .ds / .bss) | Program | Function/block | Zero ( 0 ) |
Let’s look at couple of programs on Local static variables.
Program to understand Local static variables within a function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/* Â Â Â Â Program to understand local static variable */ #include<stdio.h> Â void function1() { Â Â Â Â static int i = 44; Â Â Â Â printf("In function1: value of i is : %d \n", i); } Â int main() { Â Â Â Â static int i = 63; Â Â Â Â Â // call function1 Â Â Â Â function1(); Â Â Â Â Â // print the value of 'i' Â Â Â Â printf("In main: value of i is : %d \n", i); Â Â Â Â Â return 0; } |
Program Output:
1 2 3 4 5 |
$ gcc local-static-variable.c $ ./a.out In function1: value of i is : 44 In main: value of i is : 63 $ |
As you can see from the above output, We have two local static variables here. One in the scope of the main function and another one in function1’s scope. This will clarify that, Local static variables when declared within a function are function scoped and not visible outside of the function.
Local Static Variables Lives throughout the program:
Here is a C Program to demonstrate that The Local static variable’s lifetime is equal to the program’s lifetime.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/*     Program to demonstrate local static variable */ #include<stdio.h>  void boost() {     static int i = 50;     printf("In counter function: Value of i is : %d \n", i);      // increment 'i' by '10'     i += 10;    // i = i + 10; }  int main() {     static int j;      // call 'boost' function few times     boost();     boost();     boost();     boost();      // print the value of 'j'     printf("In main: value of j is : %d \n", j);      return 0; } |
Program Output:
1 2 3 4 5 6 7 8 |
$ gcc local-static-variable-2.c $ ./a.out In counter function: Value of i is : 50 In counter function: Value of i is : 60 In counter function: Value of i is : 70 In counter function: Value of i is : 80 In main: value of j is : 0 $ |
From the above program output, We can confirm that the local static variable i in the function boost is able to retain its value between the function calls.
So when the program started, The boost function’s variable i is created and got the value 50 (as we initialized with 50). So when we called the boost function multiple times, The value of i is increased by 10 for every call.
- In the first call to boost function, The value of i is 50, and we printed it on the console and then incremented the value by 10, Now the i value became 60.
- When we made the second call, The variable i won’t be created again, as static variables live throughout the life of the program, So i will be available and it will have the latest value 60. So when we printed the i, We got 60. Finally, we incremented the i value by 10. Now variable i became 70.
- Similarly, for the Third and fourth calls, We printed the i value and incremented it again, So we got the values as 70 and 80.
With the above example, We can say
- Static variable life is throughout the program.
- Static variable is able to retain its value between the function calls. As the static variable is not created and destroyed for every function call/return.
Global Static Variables in C Language:
The global variables or functions which are defined with the static storage class specifiers are called as the global static variables in C language.
Global static storage class variables syntax in C:
1 2 3 4 |
static datatype variable_name; Â // for functions static return_type function_name(arguments_list) |
Similar to local static variables, The global static variables also will live throughout the program. and will have the same initial value and storage location, but they differ in scope. While the local static variables are only visible in the declared function or block. The global static variables are visible to all functions in the file. But they won’t be visible outside of the declared file.
The global static variables have the Internal Linkage and It is file scoped, So the variables and functions which are declared using the internal linkage will be visible in the declared file only. As the global static variable has internal linking, You can’t access them from the other files.
📢 We can create the file-scoped variables using the global static storage class variables.
Let’s briefly look at the characteristics of global static variables.
Storage Location:
The global static variables are stored in the data segment of the RAM. ( The initialized static variables are stored in the data segment ( .bs) and the uninitialized static variables are stored in .bss segment)
Lifetime:
The Lifetime of global static variables is the same as the program. The global static variables are created when the program begins and will live throughout the life of the program and are deallocated when the program is terminated.
Scope ( Visibility ):
The global static variables are file scoped, so they will be visible to all functions in the file.
Default Value or Initial Value:
If the static variable is not initialized, Then the default value of the local static variable is Zero. ( All .bss variables will be initialized with zeros during the program startup)
Linkage:
Global static variables have the Internal Linkage.
Global Static storage calls variables Properties:
Storage Location | Lifetime | Scope | Default Value |
---|---|---|---|
Data Segment ( .ds / .bss) | Program | File | Zero ( 0 ) |
📢 So when you want to have a global variable or function, which only needs to be visible in the declared file, Then you can use the global static variables, This way we can hide our function or variables from outside files.
Program to understand the global static storage class variable in C:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
/*     Program to understand global static variable */ #include<stdio.h>  // global static variables - visible throughout the file static int g = 10;  static void update() {     // access global static variable 'g'     printf("In update: g: %d \n", g);     g += 50;  // g = g + 50; }  int main() {     // call update function     update();      // Access global static variable 'g' and print it     printf("In Main: g: %d \n", g);      // update 'g' again     update();      // print 'g' value     printf("In Main: g: %d \n", g);      return 0; } |
Program Output:
1 2 3 4 5 6 7 |
$ gcc global-static-variable.c $ ./a.out In update: g: 10 In Main: g: 60 In update: g: 60 In Main: g: 110 $ |
As we can see from the above output, The global static variable g is visible throughout the file, So The update function and main function is able to access and modify the variable g.
Extern Storage Class in C Programming Language:
The variables which are defined/declared are called as the Extern storage class specifier. We can use the extern storage class for the variables and functions.
Syntax of Extern Storage class variable in C
1 2 3 4 5 |
// for variable extern datatype variable_name; Â // for function extern return_type function_name(arguments_list) |
We can access the extern storage class variables and functions from anywhere in the program. which means we declare the variable/function in one file and can be accessed from another file.
Let’s look at the properties of extern storage class variables or functions
Storage Location:
The extern storage class variables are stored in the data segment of the RAM. ( The initialized extern variables are stored in the data segment ( .bs) and the uninitialized extern variables are stored in .bss segment)
Lifetime:
The Lifetime of extern variables is the same as the program. These variables are created when the program begins and will live throughout the life of the program and are deallocated when the program is terminated.
Scope ( Visibility ):
The extern storage class variables or functions will be visible to all files. Can be accessed from any function file in the program. The extern variables are program-scoped (or Application Scoped / Global Scoped).
Default Value or Initial Value:
If the extern storage class variable is not initialized, Then the default value of the variable is Zero. ( All .bss variables will be initialized with zeros during the program startup)
Linkage:
The extern variables have the External Linkage.
📢 External Linkage and Global Scope – This means the variables and functions which have external linkage will be accessed to all source files in the program (application). So can be accessed from any file of your program
Before looking at an example of extern storage class variables, We need to understand the difference between the declaration and definition of variables.
Extern storage class variable Declaration:
As we can access the extern variables or functions from another file as well. We can do that by specifying the declaration using the extern keyword like below.
1 2 3 4 |
extern datatype variable_name; Â // filename : main.c extern int i; |
The above statement extern int i; is the declaration of variable i. This declaration won’t create the variable, This declaration simply informs the compiler, There will be a variable named i with the integer datatype, which is going to be defined somewhere in the program, that might be within the present source file or another file.
This extern variable declaration is very much similar to the function declaration or forward declaration of the function. We are letting the compiler know that there will be a function or variable, which is going to be initialized somewhere in the program, So we can access that variable or call that function without causing any compilation errors.
📢The extern variable declaration won’t cause any memory allocation. We can declare the variables multiple times in the program using extern keyword.
Now we declared the extern variable, We need to define it somewhere in the program. Let’s say we have another file called utils.c, Where we defined the variable i
utils.c
1 2 |
// in global scope; Outside of all functions. int i = 10; |
Extern Storage class Variable Properties:
Storage Location | Lifetime | Scope | Default Value |
---|---|---|---|
Data Segment ( .ds / .bss) | Program | Program (Application) | Zero ( 0 ) |
Program to understand Extern Storage Class in C:
Let’s create a file named utils.c and define a couple of extern variables i and j. We also create a sum function as well.
utils.c
1 2 3 4 5 6 7 8 9 |
// Intializing two variables. int i = 10; int j = 20; Â // 'sum' function definition extern int sum(int num1, int num2) { Â Â Â Â return num1+num2; } |
Create another file named main.c, which is going to use the above utils.c files variables and functions.
main.c
1 2 3 4 5 6 7 8 9 10 11 12 |
#include<stdio.h>  // declare the 'i' and 'j' so that we can use them extern int i, j; extern int sum(int, int);  int main() {     // call the 'sum' function     printf("sum of %d and %d is : %d\n", i, j, sum(i, j));     return 0; } |
As you can see we have declared the variables i and j using the extern keyword, Similarly we also declared the sum function. Here we are telling the compiler that, There are two variables i and j, and function sum are defined somewhere in the program (might be in this file or another source file), So by using this declaration we are conveying to the compiler the properties of the extern variables(datatype) and functions (return value, arguments).
Run the above program using GCC compiler using the following command
1 2 3 4 |
$ gcc main.c utils.c $ ./a.out sum of 10 and 20 is : 30 $ |
As you can see from the above output, The main function from main.c file is able to access the variable values( i, j) , which are defined in the utils.c file.
Similarly, The main function is also able to call the sum function, which is declared in the utils.c file.
This is possible due to the extern storage class variables and functions. As they can be accessed from anywhere in the program.
📢If you don’t specify any storage class for global variables and functions, Then they will have the external linkage and can be accessed from all the files in the program.
Library functions storage class : The printf() and scanf() functions storage class:
If you look at the declarations of printf and scanf functions in the stdio.h, You will come to know that they also declared with the extern storage class.
Here is the prototype of the printf function from the stdio.h header file.
1 2 |
// prototype of printf function extern int printf (const char *__restrict __format, ...); |
That is the reason, We are able to call the printf and scanf and all other library functions as they have external linkage and can be accessed from other files.
📢How to see the prototype of printf function or other library functions? Please go through the following article, Where we looked at the compilation process in C language in detail.
Storage Classes in C Langauge – Conclusion:
We have looked at the Storage Classes in C language like Auto Storage class, Register Storage class, Static Storage class, and Extern storage class variables. How the storage class affects the location, lifetime, scope( visibility), Default value, and Linkage of the variable and how important it is to understand the storage classes to develop multi-file (Source files) applications.