Storage Classes in C Programming

In this tutorial, we will learn about various storage classes in C like static, auto, register and extern. We will also study the effect of storage classes on storage and visibility of variables.

A Storage class defines the scope, life-time and where to store a variable in C program. There are four storage classes defined in C programming language

  • static
  • auto
  • register
  • extern

Static Variable

A local static variable is visible only inside their own function but unlike local variables, they retain their values between function calls. We can declare static variable by adding static keyword before data type in variable declaration statement.

static data_type variable_name;
For Example:
static int sum;
  • Static keyword has different effect on local and global variables.

  • For local static variables, compiler allocates a permanent storage in heap like global variable, so that they can retain their values between function calls. Unlike global variables, local static variables are visible only within their function of declaration.

  • For global static variables, compiler creates a global variable which is only visible within the file of declaration.

  • Variables declared static are initialized to zero(or for pointers, NULL) by default.

In the following program, we declared a local and a static variable inside getVal function. Output of this programs shows that static variable retains it's value between successive function call whereas local variable vanishes when control exits function block.

#include <stdio.h>

int printVal(){
    /* Declaring a static variable */     
    static int staticVariable = 0; 
    /* Declaring a local variable */
    int localVariable = 0;
    
    /*Incrementing both variables */
    staticVariable++;
    localVariable++;
    
    printf("StaticVariable = %d, LocalVariable = %d\n", staticVariable, localVariable);
}

int main(){
   printVal();
   printVal();
   printVal();
   printVal();
   
   return 0;
}
Output
StaticVariable = 1, LocalVariable = 1
StaticVariable = 2, LocalVariable = 1
StaticVariable = 3, LocalVariable = 1
StaticVariable = 4, LocalVariable = 1

Automatic variable

A variable which is declared inside a function or block is automatic variable by default. We can declare automatic variables using auto keyword, but it is rarely used because by default every variable is automatic variable.

#include <stdio.h>

int main(){
    /* Automatic variable by default */
    int a = 5;
    /* Declaration of automatic variables using auto keyword */
    auto int b = 10;

    printf("Sum = %d", a+b);

    return 0;
}
Output Output
Sum = 15

Register Variable

Declaring a variable with register keyword is a hint to the compiler to store this variable in a register of the computer's CPU instead of storing it in memory. Storing any variable in CPU register, will reduce the time of performing any operation on register variable. We can declare register variables using register keyword.

  • The scope of register variables are same as automatic variables, visible only within their function.

  • You a only declare local variables and formal parameters of a function as register variables, global register variables are not allowed.

  • Declaring a variable as register is a request to the compiler to store this variable in CPU register, compiler may or may not store this variable in CPU register(there is no guarantee).

  • Frequently accessed variables like loop counters are good candidates for register variable.
#include <stdio.h>

int main(){
    /* Declaration of register variables using register keyword */
    register int counter;
    int sum=0;
    /* Variable counter is used frequently within for loop */
    for(counter = 1; counter <= 500; counter++){
        sum+= counter;
    }
    printf("Sum = %d", sum);
   
    return 0;
}
Output
Sum = 125250

External Variable

External variables in C are variables which can be used across multiple files. We you can declare an external variable by preceding a variable name with extern specifier. The extern specifier only tells the compiler about the name and data type of variable without allocating any storage for it. However, if you initialize that variable, then it also allocates storage for the extern variable.

  • Variables declared extern are initialized to zero by default.

  • The scope of the extern variable is global.

  • The value of the external variable exists till program termination.

Using Extern with Functions

// File: main.c

#include <stdio.h>

// Declare the external function
extern void externalFunction();

int main() {
    // Call the external function
    externalFunction();

    return 0;
}
// File: external.c

#include <stdio.h>

// Define the external function
void externalFunction() {
    printf("This is an external function.\n");
}

In this example, the externalFunction is declared with extern in the main.c file, and its actual definition is provided in the separate external.c file. When the program is compiled and linked, the linker resolves the reference to externalFunction.

Using Extern with Variables

// File: main.c

#include <stdio.h>

// Declare the external variable
extern int externalVar;

int main() {
    // Access the external variable
    printf("Value of externalVar: %d\n", externalVar);

    return 0;
}
// File: external.c

// Define the external variable
int externalVar = 42;

In this example, the externalVar is declared with extern in the main.c file, and its actual definition is provided in the separate external.c file. The linker resolves the reference to externalVar during the linking phase.


Best Practices of Using Storage Classes in C

When storage classes are used correctly, they can make C code run faster and be easier to manage. These are the best ways to do things:
  • Minimize Global Variables : Even though global variables are useful, you shouldn't use them too much. They can make it harder to understand, manage, and fix bugs in code. Instead of depending on global state, it's better to pass variables to functions directly.

  • Use Static Variables Wisely : Static variables can help you keep state between function calls. When they are used too much, though, they can make code less flexible and harder to understand. When the action of a static variable is very important, use it wisely.

  • Explicitly Use extern for Declarations : When working with variables described in other files, always use extern for declarations in the file that references the variables. This makes the code easier to read and helps find problems before they are compiled.

  • Prefer Automatic Storage for Local Variables : For local variables within a function, prefer automatic storage (i.e., not specifying a storage class) unless there is a specific reason to use static or register.

  • Document Storage Class Choices : When you use storage classes directly, include comments that show why you chose a certain one. You and other coders will be able to understand what the variable's storage properties are meant to do.

Conclusion

In C, storage classes are very important for setting the scope, visibility, and lives of variables. Developers can write code that is not only efficient but also modular and easy to update if they know how the auto, register, static, and extern storage classes work. To make C programs that work well and are easy to understand, you should pick the right storage class for variables, keep global state as small as possible, and follow best practices. Developers can make the best use of memory and make software that meets speed and maintainability standards if they know a lot about storage classes.