Storage class & its specifiers in C

Storage Class

In simple words , Storage class defines the scope and lifetime of a variable. Lets dig into this….. It tells the compiler about various features of a variables.

  1. It tells from where the variable can be accessed and from where it cannot be.
  2. Till how long the variable is going to exist in memory during execution.
  3. The default value it is going to have , if not defined.
  4. Where it is going to be stored i.e memory or cpu register, if in memory then which segment of memory.

Syntax :

storage_class_type  variable_datatype  variable_name;

Storage class consists of five specifier and are as follows.

  1. Automatic
  2. Register
  3. Static
  4. External
  5. Typedef

Storage Class
Important: Most of us thinks that there are only 4 storage class specifier and we forget about typedef which is also one of the storage class specifier… Keep in mind , so that you can choose the correct answer in Q & A section below.
Let’s see the storage class specifier in detail and before that i would advice all the readers to simultaneously practice the available programs and also the assignment programs mentioned.

  1. Automatic :

    By default all the local variables will be having automatic storage.. Do you remember your basic c program to print value of ‘a’ variable on output screen ??

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

If you see the definition of variable ‘a’ in the above program and compare it with the syntax of storage class. What do you think is missing ???? Immediately you could see that the storage class specifier is missing. Data type and name of a variable can be seen with variable initialised with some value, right ??
So, here the storage class of variable ‘a’ is implicitly automatic or that could be explicitly mentioned in the definition of a variable like

auto int a=10; // Here auto is the keyword used for automatic storage class

  1. The scope of automatic variable is within the function or block(Whatever present between the { and } braces is a block).
  2. The lifetime of automatic variable is within the function or block.
  3. The default value it holds is a garbage unless initialised.
  4. Stored in memory(stack segment).

Let’s see an example…

#include <stdio.h>

int main(void)
{ /* Block1 Start */
auto int a; 
printf("The value of a in block1 is %d\n", a);
      /* Block2 start */
      {
      int b = 100;
    
     printf("The value of a in block2 is %d\n" , a);
     printf("The value of b in block2 is %d\n" , b);
     } /* Block2 End */
  return 0;
 }/* Block1 End */

Output:
The value of a in block1 is 0
The value of a in block2 is 0
The value of b in block2 is 100    /* Code Tested with Gcc 6.3 */

Here the value of a is garbage “0” and the scope is within the block1 i.e start of block1 to end of block1, that is why we are able to access ‘a’ inside block2 as block2 is present inside block1… but what about the scope and lifetime of variable “b” ?
The scope and lifetime of “b” is within block2, so it means that “b” cannot be accessed outside block2… And results in compile time error when accessed outside block2.

#include <stdio.h>

int main(void)
{ /* Block1 Start */
auto int a; 
printf("The value of a in block1 is %d\n", a); 
      /* A block 2 started */
      {
      int b = 100;
      printf("The value of b in block2 is %d\n" , b);
      } /* Block2 End */ 
 printf("The value of b in block2 is %d\n" , b);

return 0; 
}/* Block1 End */

Output: prog.c: In function ‘main’:
prog.c:18:47: error: ‘b’ undeclared (first use in this function)
 printf("The value of b in block2 is %d\n" , b);

The variable “b” exist in memory as long as control is in block2, once the control is out of block2 the variable “b” will be deleted (i.e. memory will be deallocated).

Storage Class

Important: Automatic storage class is only for local variables and not global , if you try to declare a global variable as automatic then compiler will throw error. So, write a program and check it.

2. Register storage class :

Register storage class is similar to automatic storage class, now the question comes to our mind is that, what is the difference then ?

  1. The scope of Register variable is within the function or block.
  2. The lifetime of Register variable is within the function or block.
  3. The default value it holds is garbage unless initialized.
  4. Stored in cpu registers.

I have listed the features of register variable above and you can see the difference by yourself. The fourth Point i.e the register variables are stored in cpu registers rather than memory. But it is not necessary that, it will be stored in cpu register always. As the number of cpu registers are limited in a processor. If free register is not available then the compiler will allocate the space for the variable in memory itself. The advantage of using register storage is that, we can access variables at faster speed compared to accessing a variable value from memory during runtime.
Let’s rewrite the above code

#include <stdio.h>

int main(void)
{ /* Block1 Start */
register int a; 
printf("The value of a in block1 is %d\n", a);
    /* Block2 start */
    {
    register int b = 256;
    printf("The value of a in block2 is %d\n" , a);
    printf("The value of b in block2 is %d\n" , b);
    } /* Block2 End */
 return 0;
 }/* Block1 End */

Output:
The value of a in block1 is 0
The value of a in block2 is 0
The value of b in block2 is 256

Important:

  1. Register storage class is only for local variables and not global.
  2. We cannot use pointer to a register variable.Because it is stored in cpu register. So, write a program to check the above two points .You should get compilation error in both the cases.

3. Static Storage Class

Static storage class is very important and should have clear understanding , i will try to cover programs to demonstrate the use of static storage class in different scenario’s. Unlike, auto and register storage which are used for only local variables, static storage class can be used for local as well as global variables.
Coming to the features of static variable.

  1. The scope of static variable is either local or global.
  2. The lifetime of static variable is till the execution of program irrespective of being local or global.
  3. The default value it holds is zero unless initialized.
  4. Stored in memory(Data segment which is further divided into initialized data segment or uninitialized data segment(BSS)).

As stated in point 2, the static variables will be available in memory till program gets executed, i.e. static variables retains their value. Lets see an example.

#include <stdio.h>

static int a;      /* a is a global static variable */

void xyz(void)
{
 printf("value of a in xyz function is %d\n" , a);
 a++;
}

int main(void) 
{
 
 xyz();
 xyz();
 xyz();
 
 printf("value of a in main function is %d\n" , a);
 return 0;
}

Output:

value of a in xyz function is 0
value of a in xyz function is 1
value of a in xyz function is 2
value of a in main function is 3

The value of a is initially Zero. So, don’t get confused here assuming it as garbage.This is the point 3 as mentioned in the features of static variables.
For first call of xyz() function, value of a is zero which is printed onto screen and before returning from xyz() function, the value of a is incremented and updated to “1”.
For second call of xyz() function , value of a is “1” which is printed onto screen and before returning from xyz() function, the value of a is incremented again and now it becomes “2”… likewise it gets executed. So here the point to be noted is that the value of static variable will persist through the function calls unlike auto variable which are created once control gets into the function and will be destroyed when the control returns from the function. This defines the lifetime of static variable i.e till program executes. Next you can see that the static variable “a” is accessed from xyz and main functions because it is declared globally(global scope). If it is declared inside xyz() function then it can only be accessed inside xyz() function and not in main function (local scope).

storage-class3.png
The static variables are initialized only once . Let’s See an example program.

#include <stdio.h>

void xyz()
{
 static int a = 10; /* a is a local static variable */
 printf("value of a in xyz function is %d\n" , a);
 a++;
}

int main(void) 
{
 
 xyz();
 xyz();
 xyz();
 
 return 0;
}
Output:
value of a in xyz function is 10
value of a in xyz function is 11
value of a in xyz function is 12

If it was an auto variable then the result could be
value of a in xyz function is 10
value of a in xyz function is 10
value of a in xyz function is 10
Because auto variables are created and destroyed every time a function is invoked…….
Important :

  1. If a global variable is declared as static then the scope of that variable will be restricted to the same file and it cannot be accessed from the other files.

4. External storage class

The external storage class is the default storage class for global variable. The “extern ” keyword is used to declare external storage for a variable.

  1. The scope of extern variable is global and it can also be accessed from other files.
  2. The lifetime of extern variable is till the execution of program.
  3. The default value it holds is zero unless initialized.
  4. Stored in memory(Data segment which is further divided into initialized data segment or uninitialized data segment(BSS)).

As the name indicates, it tells the compiler that a variable exist somewhere externally(ex: file1.c) and we are going to use the very same variable in another file (ex: file2.c), so don’t allocate memory for this variable separately.
Let’s say we have two source files , file1.c and file2.c and want to use a variable which is defined in file1.c in file2.c.

Storage Class

Create a project and add two source files with the above content , execute the code and you will get output as “10”. So, when compiler see variable “a” in file2.c it does not allocate any memory for variable “a” (This is called declaration of variable).
Once you are able to execute the above code successfully, try different ways to understand the use of extern… do the following things for better understanding and let me know in comment what you observed for below points..

  1. Remove the definition of variable “a” from file1.c and execute.
  2. Remove extern keyword for variable “a” in file2.c and execute.
  3. Make the global variable “a” as static in file1.c and try to execute(refer important note mentioned for static storage class).
  4. Move the definition of ‘a’ inside main function i.e make ‘a’ as local variable and try to execute.

Important:
1. In the above sample program for extern, the instance of variable “a” in file2.c is just a declaration (memory is not allocated) means, we cannot assign any value to ‘a’ in file2.c. Try to assign value to “a” in file2.c and execute.

Typedef :

Typedef is a storage class specifier and it is used to provide alias names for data types.
Ex: typedef unsigned int UI; // Here UI is the alias name for unsigned int data type and can be used to declare unsigned integers.
UI a =100;
UI b = 200;
Let’s summarize the storage classes discussed in this post.

storage-class6.png

Q&A Section:

What is the output of the below programs ( 1 to 5) , write in comments.

 1) #include<stdio.h>
 auto int a = 100;
 main(){
 int a =50;
 printf("Value of a is %d\n", a);
 return 0;
 }  
2) #include<stdio.h>
void xyz(void)
{
static auto int a = 55;
printf("Value of a is %d\n",++a);
}
main()
{
     xyz();
     xyz();
return 0;
}
3) #include<stdio.h>
main()
{
int a = 10;
static int b = a;
printf(" a*b = %d\n" , a*b);
return 0;
}

Execute this program to find out very important property of static variable.
In the above explanation of static storage class , i didn't mention this point.
4)  #include<stdio.h>
typedef static int SI;
main()
{
SI a = 10;
printf(" a = %d\n" , a);
return 0;
}
5)  #include<stdio.h>
int main()
{
auto int a;
static int b;
register int c;

printf(" Value of a is %d and Address is %p\n" , a , &a);
printf(" Value of b is %d and Address is %p\n" , b , &b);
printf(" Value of c is %d and Address is %p\n" , c , &c);
return 0;
}

This is all about storage class and its specifier , hope you liked it. Please let me know in comments if something needs to be added or if you find any corrections, so that i can update the post. And finally a request to all the readers not to forget to like , comment and share.

Leave a comment