What are the uses of different storage classes

Thread Starter

anukalp

Joined Jul 28, 2018
158
Hi,

I need some help to understand storage classes in c language. I've been searching on internet and trying to understand uses of different storage classes. I have been read the this link https://en.wikiversity.org/wiki/C/Storage_Classes

Variable store at specific memory location and storage means space to store variable value in memory.

There are the four type of storage classes
  1. Auto
  2. Register
  3. Extern
  4. Static

register: this storage class specifier can be used to indicate to the compiler that the variable will be used frequently and it should be placed in a CPU register

static: this storage class specifier is used for local and global variable

extern: this storage class specifier is used to declare a variable or function that is defined in another module.

auto: this is the default storage class specifier for variables defined inside a function. auto can be used only inside functions

Can anyone help me with storage classes in c language. I don't understand why we need to specify storage classes. I am trying to understand what's the need of storage classes and What are the uses of different storage classes in program ?
 

bogosort

Joined Sep 24, 2011
696
The variables and functions we create in source code must be stored in memory during execution of the program. In C, along with the names of the variables and functions -- i.e., the identifiers we use to refer to the variables or functions -- the programmer can specify two other parameters during declaration: storage duration and linkage.

Storage duration determines the lifetime of a variable, i.e., how long we can expect it to remain in memory during program execution. A synonym for storage duration is extent. The three possibilities are:
  • static duration: available for the lifetime of the program, declared with the keyword 'static';
  • automatic duration: available only during the execution of the block of code in which it was declared;
  • allocated duration: available until it is explicitly destroyed by a call to free().
Automatic duration is the default. If in the declaration of a variable we don't specify static duration, then the variable has auto duration -- it will exist only for the lifetime of the block (the code enclosed in braces) in which it was declared. (We can explicitly use the 'auto' keyword, but no one does.)

For example, suppose we define a function as below:

C:
int do_something(int n)  {
  static int foo = 10; // static duration
  int bar = 100;       // automatic duration
  int result;          // automatic duration

  if ( n > 0 ) {
    result = n + bar;
    bar++;  // this has no effect!
  }  else {
    result = n + foo;
    foo++;
  }

  return result;
}
Suppose we call the function as follows: do_something(0). The 'else' statements will run, and the function will return 10. But since 'foo' was declared with static duration, it exists for the lifetime of the entire program. This means that if we call do_something(0) again, it will return 11 (because 'foo' was incremented and saved).

In contrast, no matter how many times we call do_something(1), it will always return 101: each time program execution enters the function block, the 'bar' variable is created anew with the value 100; unlike 'foo', the 'bar' variable has auto duration and is not saved across function calls.

Allocated duration is implicitly used in dynamic memory allocation, such as with malloc(). The storage that is allocated has no identifier; instead we refer to it with a pointer, a variable which does have an identifier and, hence, auto or static extent. This decoupling of the storage and identifier duration can lead to memory leaks if the programmer is not careful. Consider:

C:
int do_something_else(void) {
  int *quux = malloc( sizeof(int) ); // oops!
  *quux = 42;
  return *quux;
}
This function dynamically allocates memory to hold one integer, then assigns the value 42 to that memory location and returns the value. However, the variable 'quux' has auto duration, but the storage it points to has allocated duration, which can only be destroyed by a call to free(). As soon as the function block ends, the 'quux' variable goes away while the allocated storage remains "in limbo" -- we can never reclaim or free it. This is a memory leak: every time do_something_else() is called, the running program will lose available memory; if the program runs for a long time, eventually it will crash. The proper way to deal with this kind of situation is to allocate the memory outside the function, pass the pointer to the memory as an argument to the function, and then free the memory back outside the function.

Finally, the other aspect of variable and function declaration is linkage, which determines the scope of availability of the variable or function. There are three possibilities:
  • no linkage: the identifier has block scope;
  • internal linkage: the identifier has no visibility outside of the translation unit (file) in which it was declared;
  • external linkage: the identifier has program-wide visibility.
Note that linkage and duration refer to somewhat similar but distinct aspects: duration determines how long the identifier is valid, while linkage determines the identifier's visibility (with respect to the rest of the code). Linkage matters when the code in your program is spread across several source files.

Identifiers with external linkage are "global": they can be seen by all of the code in all of the source files (though it is good programming practice to avoid global variables and functions when possible). All non-static functions have external linkage, as do all variables declared outside of main and without the 'static' keyword. When we declare an identifier with the keyword 'extern', we're explicitly telling the compiler that the identifier is defined in another source file.

Functions and variables with internal linkage can only be seen by the code in the file in which they were declared. We specify internal linkage with the 'static' keyword, which is an unfortunate overloading (there's no such thing as "static linkage").

Putting it all together:

C:
extern int foo_external; // static duration, external linkage (explicit)
int foo2_external; // static duration, external linkage (implicit)
static int bar_internal; // static duration, internal linkage

int func_external(int);  // external linkage
static int func_internal(int);  // internal linkage

int main(void) {
  int i;  // auto duration (lifetime of program since at top-level of main), no linkage
  foo2_internal = 42;

  for ( i = 0; i < 10; ++i ) {
    int result = 0;  // auto duration, no linkage
    if ( i % 2 )
      result = func_internal(i);
    else
      result = func_external(i);

    foo2_external = result + foo2_internal;
  }
  return 0;
}

static int func_internal(int n) {
  static int var_static = 5;  // static duration, no linkage
  int var_auto = n;  // auto duration, no linkage

  return var_auto + var_static++;
}
Of the three variables with static duration (lines 1-3), the first two have external visibility and are (presumably) defined in another file. The 'extern' keyword is optional, though recommended as it makes obvious to anyone reading that the variable is defined in another file.

Of the two function declarations (lines 5 and 6), the one declared as 'static' is visible only in this source file. Consequently, it's defined in this source file (24 through 28); the external function can be defined in another file, and it can be used by any source file that includes its declaration (which is typically done in a header file). The 'extern' keyword for functions is optional, though generally not used.

Note line 13: it declares and defines a variable 'result' within a for-loop block. This means that it will exist and be visible only within the block; code outside the block trying to access 'result' would produce a compiler error.
 
Last edited:

Thread Starter

anukalp

Joined Jul 28, 2018
158
The variables and functions we create in source code must be stored in memory during execution of the program. .
Thank's bogosort for your detail explanations

let's start with one example

so the variable declared inside block or function without any storage class specifier called automatic

Program to understand automatic variable
C:
#include <stdio.h>

int addition(int x, int y);

int main(void)
{
       int a = 2; int b = 3;
    
     int sum;

     sum = addition(a, b);
    
     printf("sum = %d \n", sum);
    
    return 0;
}

int addition(int x, int y)
   {
       int result;

       result = x +y ;

       return result;
   }
Here, the variable 'result' is declared inside the function 'addition' and thus can be used only inside the function. There is no need to put 'auto' while declaring these variables because these are by default auto.

here are two variable 'result and 'sum' so are they both automatic variable ?
 

bogosort

Joined Sep 24, 2011
696
Here, the variable 'result' is declared inside the function 'addition' and thus can be used only inside the function. There is no need to put 'auto' while declaring these variables because these are by default auto.

here are two variable 'result and 'sum' so are they both automatic variable ?
You have six variables in your program: 'a', 'b', 'sum', 'x', 'y', and 'result'. Since they were all declared without the 'static' keyword and within the scope of main(), they all have automatic duration. In particular, 'a', 'b', and 'sum' will exist for the lifetime of the program, and 'x', 'y', and 'result' will exist only while addition() is executing.

In terms of linkage, all the variables have no linkage: the 'a', 'b', and 'sum' variables are visible only in main(), while the 'x', 'y', and 'result' variables are visible only in addition(). In contrast, the addition() function has external linkage since it was not declared as 'static'. It can be called from anywhere in the source code, as well as in other source files, provided they include its declaration.
 

Thread Starter

anukalp

Joined Jul 28, 2018
158
It can be called from anywhere in the source code, as well as in other source files, provided they include its declaration.
Thanks. The variable that have to used by many function can be declared as external variable

Program to understand external variable
C:
#include <stdio.h>

extern int x;
void function1(void)
{
     int i;
     for (i = 0; i < 10; i++)
     {
       x = 0;
       function2(20);
     }
}
void function2(int n)
{
    int i;
    for (i = 0; i < n; i++)
    {
      function3(5);
       x += 5;
    }
}

void function3 (int n)
{
     x = n ;
}
int main(void)
{
 
    function3(5);
  
    x -= 6;
   
    return 0;
}
Here an external variable is initialized and this function can be used in all function including main function.this program consist of four function I have declared variable x that are using in all others functions

I don't know my example is relevant. Please correct me if I am wrong in program
 

Ian Rogers

Joined Dec 12, 2012
1,136
Thanks. The variable that have to used by many function can be declared as external variable
extern is to inform the complier that this variable is declared in another C file in your project. Typically used when a large data structure is in another file... ie a font for a display, it's usually too large to incorporate in the main C file..

register is when you instruct the compiler to use working registers... ie on the x86 platform, the AX register for instance.. This will speed the code up if you are using long iterations ( large for / do loops ).

static / auto has already been well explained..

To use variables within one C file ( declared at the beginning ) are classed as global.
variables declared within a function are classed as local
 

Thread Starter

anukalp

Joined Jul 28, 2018
158
extern is to inform the complier that this variable is declared in another C file in your project. Typically used when a large data structure is in another file... ie a font for a display, it's usually too large to incorporate in the main C file..
Thanks Ian Rogers,

I have doubt on my understanding so I have explained with example

Is my example correct ? Does it require any modification for external variable
 

Ian Rogers

Joined Dec 12, 2012
1,136
You do not need to declare a variable extern is it resides within the scope of the file..

If you have multiple files in a project, most variables can be declared in a header! Bit! if you have a C file to be included and do not choose to write a header, then just declare the variables as normal, then re-declare as extern in the file you wish to use them in...

lets say your main looks like this:-
C:
#include<stdio.h>

UINT veryGlobal;

int main(){
   veryGlobal = 1;
}
this is main.c….

now we have another file we'll call externalCode.c.. This is included into the build.

C:
#include<stdio.h>

extern UINT veryGlobal;

int externalFunction(){
   veryGlobal = 2;
}

Personally I very rarely use extern as all C++ programmers cringe like billyO..
The variable has no protection and can be modified inadvertently!!

As I said before I only ever use extern with fonts and tables....
 

bogosort

Joined Sep 24, 2011
696
register is when you instruct the compiler to use working registers... ie on the x86 platform, the AX register for instance.. This will speed the code up if you are using long iterations ( large for / do loops ).
Note that in C 'register' is a suggestion to the compiler, not an instruction. It should be avoided in general, especially on complex architectures like x86. If a programmer knows that they can out-optimize the compiler, they should take full control by usuing inline assembly or calling a function written in assembly.
 

Thread Starter

anukalp

Joined Jul 28, 2018
158
Thank you so much to stay in this discussion. Let's talk about the next example

There are tow types of static variable
  • Local static variable
  • Global static variable
Local static variable : Program to understand Local static variable

Static local variable can only used inside function

C:
#include <stdio.h>

void function()
{
    static int x = 0;
 
    x++;
 
    printf("%d\n", x); // outputs the value of x
}

int main()
{
    function();
 
    function();
 
    function();
 
    return 0;
}

Static Global variable : Program to understand Global static variable

Static Global variable can only used outside function

C:
#include <stdio.h>

static int x = 0;

void function()
{
 
    x++;
 
    printf("%d\n", x); // outputs the value of x
}

int main()
{
    function();
 
    function();
 
    function();
 
    return 0;
}
If we observe the output of both program's there is no difference. Both program print 1, 2 and 3

What's the basic difference between a static local and global variable other then declaration ?
 

bogosort

Joined Sep 24, 2011
696
Is my example correct ? Does it require any modification for external variable
We use 'extern' in a declaration to tell the compiler (and the programmer) that the corresponding variable refers to a variable of the same name that's declared/defined outside the current block of code. In your example, 'x' is declared outside of any block of code, so it doesn't need the 'extern' specifier. Even if it was declared/defined in another file, it wouldn't need to be 'extern', though in such cases it's a good thing to do for the programmer's sake.

I've rewritten your example to better demonstrate the effects of linkage. Note that in my version, I use 'extern' only inside blocks of code (i.e., code enclosed by braces {...}). It's not necessary to re-declare a variable with external linkage -- in fact, it's rarely done -- but it helps show the purpose and behavior of 'extern'.

So, for example, on line 12 I use the "global" 'x' variable without re-declaring it. This is totally fine for small programs, where it is obvious to anyone reading the program which 'x' I am referring to. But in a giant program, it can be confusing to suddenly refer to some variable 'x' that's defined/declared elsewhere in the code (even in the same file). In these cases, we can re-declare the variable as 'extern', which is what I do with 'y' on line 13.

Notice how important that 'extern' specifier is when re-declaring a variable with external linkage. On line 14, I re-declare 'z' without 'extern' -- but this introduces a new variable, with the same name but of automatic duration and no linkage. In effect, the 'z' declared in main() hides the "global" 'z'. The same thing happens in function1() with 'y'.

C:
#include <stdio.h>

static void function1(void);  // static duration, internal linkage

int x;     // static duration, external linkage
int y = 0; // same
int z = 0; // same

int main(void)
{
  x = 0;        // same 'x' as above
  extern int y; // same 'y' as above
  int z;        // this 'z' HIDES the 'z' above!

  y = 42;
  z = 10;

  function1();

  printf( "x: %d, y: %d, z: %d\n", x, y, z );
  return 0;
}

static void function1(void)
{
  int i;        // auto duration, no linkage
  extern int x; // same 'x' as above
  int y;        // this 'y' HIDES the 'y' above!

  for ( i = 0; i < 5; i++ )
  {
    ++x;
    ++y; // this will disappear at end of function!
    ++z;
  }
}
This produces:
Code:
x: 5, y: 42, z: 10
 

bogosort

Joined Sep 24, 2011
696
There are tow types of static variable
  • Local static variable
  • Global static variable
So-called "local" and "global" variables are not technical terms in C. We pretty much all know what we mean when someone says that a variable is "global", but what does "local" mean? Local to what? It's clearer to think in terms of duration (auto or static) and linkage (none, internal, or external).

If we observe the output of both program's there is no difference. Both program print 1, 2 and 3

What's the basic difference between a static local and global variable other then declaration ?
This is why "global" and "local" aren't very useful. In your first program, 'x' has static duration and no linkage. In other words, its lifetime is the entirety of the program but no other code can reference it other than the function. In your second program, 'x' has static duration and internal linkage: it lives for the entirety of the program and can be referenced by any code in the source file. The second version is not "global" in the sense we usually think of it, which means accessible by all code in all source files.
 
Top