Storage classes in c

A storage class defines the scope (visibility) and life-time of variables and/or functions within a C Program. These specifiers precede the type that they modify. The following are common Storage Classes in C Program,

Auto Storage Class in C

The auto storage class is the default storage class for all local variables.

{
   int mount;
   auto int month;
}

The example above defines two variables with the same storage class, auto can only be used within functions, i.e., local variables.

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
======
3 2 1

Register Storage Class in C

The register storage class is used to define local variables that should be stored in a register instead of RAM. This means that the variable has a maximum size equal to the register size (usually one word) and can’t have the unary ‘&’ operator applied to it (as it does not have a memory location).

{
   register int  miles;
}

The register should only be used for variables that require quick access such as counters. It should also be noted that defining ‘register’ does not mean that the variable will be stored in a register. It means that it MIGHT be stored in a register depending on hardware and implementation restrictions.

The following C program demonstrates the visibility level of register variables.

The following piece of code is trying to get the address of variable i into pointer variable p but it won’t succeed because i is declared register; therefore following piece of code won’t compile and exit with error “error: address of register variable requested”.

#include <stdio.h>
 
int main()
{
  register int i = 10;
  int *p = &i; //error: address of register variable requested
 
  printf("Value of i: %d", *p);
  printf("Address of i: %u", p);
 
}

Below code will execute without an error, you can see the way register storage class in C used in both the program

#include <stdio.h>
 
int main()
{
  int i = 10;
  register int *a = &i;
 
  printf("Value of i: %d", *a);
 
}

Static Storage Class in C

The static storage class instructs the compiler to keep a local variable in existence during the life-time of the program instead of creating and destroying it each time it comes into and goes out of scope. Therefore, making local variables static allows them to maintain their values between function calls.

The static modifier may also be applied to global variables. When this is done, it causes that variable’s scope to be restricted to the file in which it is declared.

In C programming, when static is used on a class data member, it causes only one copy of that member to be shared by all objects of its class.

#include <stdio.h>
 
/* function declaration */
void func(void);
 
static int count = 5; /* global variable */
 
main()
{
   while(count--)
   {
      func();
   }
   return 0;
}
/* function definition */
void func( void )
{
   static int i = 5; /* local static variable */
   i++;

   printf("i is %d and count is %d\n", i, count);
}

You may not understand this example at this time because I have used function and global variables, which I have not explained so far. So for now let us proceed even if you do not understand it completely. When the above code is compiled and executed, it produces the following result:

i is 6 and count is 4
i is 7 and count is 3
i is 8 and count is 2
i is 9 and count is 1
i is 10 and count is 0

The following another C program demonstrates the visibility level of static variables.

Extern Storage Class in C

The extern storage class is used to give a reference of a global variable that is visible to ALL the program files. When you use ‘extern’, the variable cannot be initialized as all it does is point the variable name at a storage location that has been previously defined.

When you have multiple files and you define a global variable or function, which will be used in other files also, then extern will be used in another file to give reference of defined variable or function. Just for understanding, extern is used to declare a global variable or function in another file.

The extern modifier is most commonly used when there are two or more files sharing the same global variables or functions as explained below.

First File: main.c

#include <stdio.h>
 
int count ;
extern void write_extern();
 
main()
{
   count = 5;
   write_extern();
}

Second File: support.c

#include <stdio.h>
 
extern int count;
 
void write_extern(void)
{
   printf("count is %d\n", count);
}

Here, extern keyword is being used to declare count in the second file whereas it has its definition in the first file, main.c. Now, compile these two files as follows:

 $gcc main.c support.c

This will produce a.out executable program when this program is executed, it produces the following result:

5

So the above discussed are the most common storage classes in C Programming Language, which every programmer must know.

Storage Class Specifiers

There are four storage class specifiers in C as follows, typedef specifier does not reserve storage and is called a storage class specifier only for syntactic convenience. It is not a storage class specifier in the common meaning.

  • auto
  • register
  • extern
  • static
  • typedef

 

  • The auto and register specifiers give the declared objects automatic storage class and may be used only within functions. Such declarations also serve as definitions and cause storage to be reserved.
  • A register declaration is equivalent to an auto declaration, but hints that the declared objects will be accessed frequently.
  • Only a few objects are actually placed into registers, and only certain types are eligible; the restrictions are implementation-dependent. However, if an object is declared register, the unary & operator may not be applied to it, explicitly or implicitly.
  • The rule that it is illegal to calculate the address of an object declared register. but actually taken to be auto is new.
  • The static specifier gives the declared objects static storage class. and maybe used either inside or outside functions.
  • Inside a function, this specifier causes storage to be allocated and serves as a definition; for its effect outside a function.
  • A declaration with extern, used inside a function, specifies that the storage for the declared objects is defined elsewhere; for its effects outside a function.

typedef Storage Class Specifier:

The typedef specifier does not reserve storage and is called a storage class specifier only for syntactic convenience. At most one storage class specifier may be given in a declaration. If none is given, these rules are used: objects declared inside a function are taken to be auto; functions declared within a function are taken to be extern; objects and functions declared outside a ‘function are taken to be static, with external linkage.

Declarations whose storage class specifier as typedef do not declare objects; instead, they define identifiers that name types. These identifiers are called typedef names.

typedef-name: identifier

A typedef declaration attributes a type to each name among its declarators in the usual way. Thereafter, each such typedef name is syntactically equivalent to a type specifier keyword for the associated type.

For example, after

typedef long Blockno, *Blockptr;
typedef struct { double r, theta; } Complex;

the constructions

Blockno b;
extern Blockptr bp;
Complex z, *zp;

are legal declarations. The type of b is long, that of bp is “pointer to long,” and that of z is the specified structure; zp is a pointer to such a structure.

typedef does not introduce new types, only synonyms for types that could be specified in another way. In the example, b has the same type as any other long object.

Typedef names may be redeclared in an inner scope, but a non-empty set of type specifiers must be given.

For example,

extern Blockno;

does not redeclare Blockno, but

extern int Blockno;

does.