Storage Classes in C

We use the storage class in the C language for determining the visibility, lifetime, initial value, and memory location of any given variable. The storage classes define the visibility (scope) and the lifetime of any function/ variable within a C program. These classes precede the type that they are going to modify.

In this article, we will take a closer look at Storage Classes in C according to the GATE Syllabus for CSE (Computer Science Engineering). Read ahead to know more.

Table of Contents

Types of Storage Classes in C

There are four different types of storage classes that we use in the C language:

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

Use of Storage Class in C

A variable given in a C program will have two of the properties: storage class and type. Here, type refers to any given variable’s data type, while the storage class determines that very variable’s lifetime, visibility, and also its scope.

Summary of Storage Classes in C

Class Name of Class Place of Storage Scope Default Value Lifetime
auto Automatic RAM Local Garbage Value Within a function
extern External RAM Global Zero Till the main program ends. One can declare it anywhere in a program.
static Static RAM Local Zero Till the main program ends. It retains the available value between various function calls.
register Register Register Local Garbage Value Within the function

Automatic Storage Class

It is also known as the auto storage class, and it acts as the default storage class for all the variables that are local in nature.

For example,

{

int mount;

auto int month;

}

Look at the example that we used above- it defines two of the variables in the very same storage class. One can use ‘auto’ only within the functions- or the local variables.

Features of automatic variables:

  • The allocation of memory for these variables occurs automatically during the runtime.
  • The scope of an automatic variable is limited to that block in which we are defining them.
  • The visibility of these variables is also limited to that block in which we are defining them.
  • The initialization of these variables is, by default, a garbage value.
  • The memory that is assigned to an automatic variable gets free when it exits from a block.
  • We use the keyword auto to define the automatic variables.
  • Any local variable that exists in the C language is, by default, automatic in nature.

Let us look at an example,

#include <stdio.h>

int main()

{

int p; //auto

char q;

float r;

printf(“%d %c %f”,p,q,r); // to print the initial default value of the automatic variables p, q, and r.

return 0;

}

The output generated here would be:

garbage garbage garbage

Let us look at another example,

#include <stdio.h>

int main()

{

int p = 10,i;

printf(“%d “,++p);

{

int p = 20;

for (i=0;i<3;i++)

{

printf(“%d “,p); // 20 will be printed here 3 times because it is the given local value of p

}

}

printf(“%d “,p); // 11 will be printed here since the scope of p = 20 has finally ended.

}

The output generated here would be:

11 20 20 20 11

External Storage Class

It is also known as the extern storage class, and we use it for giving a reference of any global variable which is visible to all the files present in a program. When using the extern storage class, we cannot initialize the variable. However, note that it points to the name of the variable at any storage location that we have already defined (previously).

Whenever we have multiple numbers of files while we are trying to define any global variable or a function (that will be used in various other files too), then we will use the extern in another file for providing the reference of the defined function or variable. In simpler words, we use the entern for declaring a function or a global variable in another file.

The most common use of the extern modifier is when we have two or more than two files that share a similar global variable or function.

For example:

main.c (File 1) –

#include <stdio.h>

int count ;

variable void write_variable();

main() {

count = 38;

write_variable();

}

support.c (File 2) –

#include <stdio.h>

variable int count;

void write_variable(void) {

printf(“The variable for the program is %d\n”, count);

}

In this example, we have used the extern keyword for declaring the variable available in the second file. On the other hand, its definition actually resides in the main.c (that is its first file). Now, the compilation of both of these files will be as follows:

$gcc main.c support.c

This step will generate a program a.out that is executable in nature. When we perform the execution of this program, we will get a result as follows:

The variable for the program is 38

The features of external variables:

  • We use the external storage class for conveying to the compiler that the variable that has been defined as the extern has been declared using an external linkage that exists elsewhere in any program.
  • One can only perform the initialization of an external variable globally. In other words, one cannot perform the initialization of an external variable within any given method or block.
  • The variables that are declared as extern have no allocation of memory. It only has a declaration, and it intends to specify that the given variable has been declared elsewhere in the available program.
  • An external integral type’s default initial value is going to be 0, or else it is null.
  • We can initialize an external variable multiple times, but we can only initialize it a single time.
  • When we declare a variable as external, the compiler will start searching for that variable for initialization somewhere in the available program. It might be static or extern. In case it isn’t, the compiler will ultimately generate an error (a compile-time error).

Let us look at an example,

#include <stdio.h>

int a;

int main()

{

extern int a; // variable a is defined globally, the memory will not be allocated to a

printf(“%d”,a);

}

The output generated here would be:

0

Let us look at another example,

#include <stdio.h>

int main()

{

extern int x; // The compiler will start searching here if a variable x has been defined and initialized in the program somewhere or not.

printf(“%d”,x);

}

int x = 20;

The output generated here would be:

20

Let us look at one final example,

extern int x;

int x = 10;

#include <stdio.h>

int main()

{

printf(“%d”,x);

}

int x = 20; // the compiler will generate an error at this line in the output

The output generated here would be:

Compile-time error

Static Storage Class

This type of storage class gives an instruction to a compiler to keep the given local variable around during the program’s lifetime- instead of creating it and then destroying it every time it comes into a scope and goes out of it. Thus, when we make a local variable static, it allows the variable to maintain the values that are available between various function calls.

We may also apply a static modifier to a global variable. When we do so, it will cause the scope of the variable to be restricted to that file in which its declaration happened.

In a C programming language, when we use the static on a global variable, it will cause all the objects present in a class to share a single copy of that given member.

For example,

#include <stdio.h>

/* declaration of function */

void func(void);

/* a global variable */

static int count = 10;

main() {

while(count–) {

func(); /* increment of function */

}

return 0;

}

void func( void ) {

/* definition of function */

static int x = 10; /* a local type of static variable */

x++;

printf(“x is %d and the count is %d\n”, x, count);

}

The compilation and execution of this code mentioned above will produce the result as follows:

When the above code is compiled and executed, it produces the following result −

x is 11 and the count is 9

x is 12 and the count is 8

x is 13 and the count is 7

x is 14 and the count is 6

x is 15 and the count is 5

Features of static variables:

  • Those variables that we define as static specifiers are capable of holding their assigned value that exists between various function calls.
  • The static local variables are only visible to the block or the function in which we have defined them.
  • We can declare the very same static variable multiple times, but we can only assign it a single time.
  • The initial value of a static integral variable, by default, is 0. Else, it is null.
  • We use the static keyword in the case of a static variable.
  • The visibility of any static global variable stays limited to that file in which we have declared it.

Let us look at an example,

#include<stdio.h>

static float f;

static int i;

static char c;

static char s[100];

void main ()

{

printf(“%d %d %f %s”,c,i,f); // the initial default value of c, i, and f will be printed.

}

The output generated here would be:

0.000000 0 0 (null)

Let us look at another example,

#include<stdio.h>

void sum()

{

static int x = 20;

static int y = 34;

printf(“%d %d \n”,x,y);

x++;

y++;

}

void main()

{

int a;

for(a = 0; a< 3; a++)

{

sum(); // Given static variables will hold their values between the various function calls.

}

}

The output generated here would be:

20 34

21 35

22 36

Register Storage Class

We use the register storage class for defining the local variables that must be stored in any register, and not in a RAM. It means that the maximum size of this variable is equal to that of the register size (it is usually one word). Also, we cannot apply the ‘&’ unary operator to it because it has no memory location.

For example,

{

register int miles;

}

We must only use the register in the case of those variables which require quick access, such as the counters. We must also note that defining a register doesn’t mean that this variable would be stored in any register. It rather means that this variable MIGHT or might not be stored in a register. It totally depends on the hardware and also the restrictions of implementation.

Features of register variables:

  • Those variables that we define as the register have their memory allocation into the CPU registers. It depends totally upon the size of the memory that remains in the CPU.
  • Its access time is comparatively much faster than that of the automatic variables.
  • One cannot dereference a register variable. In other words, one cannot make use of the ‘&’ operator in the case of a register variable.
  • The default initial value of any given register local value will always be 0.
  • We use the register keyword for the variable that must be stored in a CPU register. However, whether a variable must be stored in a register or not is always going to be the choice of the compiler.
  • One can easily store the pointers in a register. It means that any register is capable of storing the given variable’s address.
  • We cannot store a variable into a register since we can’t really utilize more than one storage specifier for the very same variable.

Let us look at an example,

#include <stdio.h>

int main()

{

register int x; // A variable x has memory allocation in the CPU register. Here, the initial value of x, by default, is 0.

printf(“%d”,x);

}

Thus, the output generated here would be:

0

Practice Problems on Storage Classes in C

1. What would be the output of the following program?

#include<stdio.h>

int func(){

static int a=0;

int b=0;

a++;

b++;

printf(“a= %d and b= %d\n”, a, b);

}

int main() {

func();

func();

func();

return 0;

}

A. a= 2 and b= 1

a= 2 and b= 1

a= 3 and b= 2

B. a= 1 and b= 2

a= 2 and b= 1

a= 3 and b= 2

C. a= 1 and b= 2

a= 2 and b= 2

a= 3 and b= 1

D. a= 1 and b= 1

a= 2 and b= 1

a= 3 and b= 1

Answer – D. a= 1 and b= 1

a= 2 and b= 1

a= 3 and b= 1

2. What would be the output of the following program?

#include<stdio.h>

int main(){

int x=20;

auto int y=30;

printf(“%d %d”,x,y);

return 0;

}

A. 10 10

B. 20 30

C. 30 20

D. -10 -10

Answer – B. 20 30

3. Which of these is true for a static variable?

1. The static local variables are only visible to the block or the function in which we have defined them.

2. We can declare the very same static variable multiple times, but we can only assign it a single time.

3. The initial value of a static integral variable, by default, is 0. But it is never null.

4. We use the static keyword in the case of a static variable.

A. 1, 2, 3

B. 2, 3, 4

C. 1, 2, 4

D. 1, 3, 4

Answer – C. 1, 2, 4


FAQs

What is the difference between a type and a storage class?

A variable given in a C program will have two of the properties: storage class and type. Here, type refers to any given variable’s data type, while the storage class determines that very variable’s lifetime, visibility, and also its scope.

What type of variables are stored in the storage classes?

The storage classes store the local variables, but can give reference to a global variable. Local variables are those variables that are declared inside any given block. These are also known as automatic variables. They only exist inside those blocks in which we declared them. On the other hand, global variables are declared outside any function. Thus, these are accessible to all the functions present in a program.

Is a register variable faster than the local variable?

The register keyword helps a user to declare the register variables, and these were actually supposed to be faster as compared to the local variables. But the modern compilers these days are very commendable at the optimization of codes. Thus, the chances of making a program faster just by using a register variable are very rare these days.
Unless and until we are working on any embedded systems where we are aware of the process of code optimization for any given application, the register variables are of no use.

Keep learning and stay tuned to get the latest updates on GATE Exam along with GATE Eligibility CriteriaGATE 2023GATE Admit CardGATE Syllabus for CSE (Computer Science Engineering)GATE CSE NotesGATE CSE Question Paper, and more.

Also Explore,

Leave a Comment

Your Mobile number and Email id will not be published.

*

*