Storage Classes in C

What is Storage Class in C?

The variables declared in the C language are totally different from other languages because we can specify the same variable in different blocks of the C program

When we declare a variable one needs to mention not only its data type but also the storage classes in C. The storage class tells the compiler

  1. Where the variable is store
  2. What is the default value of the variable
  3. What is the scope of the variable
  1. What is the life of the variable?

Scope: The area or the block in which we have defined the variable in the C program is called the scope of the variable.

Life: It specifies how long the variable will be active in the area which we have defined.

The four storage classes used in C language are:

Automatic storage class (auto): 

  • The variables which are defined in this storage class in C are called auto variables
  • Generally, auto variables are declared inside the function. 
  • Suppose we declare a variable inside the function and if we don’t specify the storage class in default it will be treated as auto variables.
  • Auto variables are safe because they cannot be accessed by other functions.

Ex: auto Int a, b;

  1. Storage: in CPU memory.
  2. Default value: garbage values
  3. Scope: local to that block in which the variables are defined.
  4. Life: till the control remains within the block in which the variable is defined.

C program using auto

#include <stdio.h>
void demonstrateAuto() {
    // The 'auto' keyword is usually omitted, as it's the default for local variables
    auto int x = 10; // Declare and initialize an automatic variable
    // 'x' exists only within the scope of this function. It's created when the function
    // starts and destroyed when the function ends. Its memory is allocated on the stack.
    printf("Inside the function: x = %d\n", x);
    // Modify the value of 'x'
    x = 25;
    printf("Inside the function (modified): x = %d\n", x);
    {  // A nested block to demonstrate scope
        auto int y = 5;  // Another automatic variable with a different scope
        printf("Inside the nested block: y = %d\n", y);
        // 'y' is accessible only within this inner block
    }
    // Uncommenting the next line would cause an error, as 'y' is out of scope
    // printf("Outside the nested block: y = %d\n", y);
}
int main() {
    // 'x' declared within demonstrateAuto is not accessible here
    // It's a different variable with the same name due to scope differences
    demonstrateAuto(); // Call the function to see 'auto' in action
    return 0;
}

Output:

Inside the function: x = 10
Inside the function (modified): x = 25
Inside the nested block: y = 5

Extern Storage Class: 

  • The variables that are declared under the extern storage class are called extern variables.
  • Generally, the external variables are declared outside the function and are called as global variables. 
  • The extern variables can be accessed by all functions. If the same variables are declared as auto and extern storage class then it will be given priority to auto storage class by hiding the extern storage class.
extern int a, b;

storage: storage memory.

Default value: 0

Scope: globally declared

Life: as long as the program execution does not come to an end.

C program using extern

File 1: extern_declaration.c

#include <stdio.h>
// extern declaration of variables
extern int sharedData;  // Declare that 'sharedData' is defined elsewhere
extern void modifySharedData(int newValue); // Declare the function prototype
int main() {
    // 'sharedData' is accessible here, even though it's defined in another file
    printf("Initial value of sharedData in main: %d\n", sharedData); 
    // Call the external function to modify the shared data
    modifySharedData(15);  
    // Observe the updated value
    printf("Modified value of sharedData in main: %d\n", sharedData); 
    return 0;
}

File 2: extern_definition.c

// Definition of the extern variables
int sharedData = 10;  // Global variable, accessible across files
// Definition of the extern function
void modifySharedData(int newValue) {
    sharedData = newValue; // Update the shared variable's value
}

output:

Initial value of sharedData in main: 10
Modified value of sharedData in main: 15

Static Storage Class: 

  • The variables which are declared in this storage class are called static variables. 
  • They can be declared either inside or outside the function. 
  • If the static variables are declared inside the function they are treated as auto variables. 
  • If the static variables are declared outside the function they are treated as extern variables.
  • The value of static variables persists at each call and the last change made in the value of the static variable remains throughout the program.
static int a, b;

Storage: Memory

Default value: 0

Scope: either globally or locally

Life: the value of the variable persists between different function calls.

C program using static 

#include <stdio.h>
void staticDemo() {
    // Declare and initialize a static variable
    static int count = 0; 
    // 'count' retains its value between function calls. It's initialized only once.
    printf("Function called %d times\n", count);
    // Increment the static variable for the next call
    count++; 
}
int main() {
    // Call the function multiple times to observe the static variable's behavior
    for (int i = 0; i < 5; i++) { 
        staticDemo();
    }
    return 0;
}

Output:

Function called 0 times
Function called 1 times
Function called 2 times
Function called 3 times
Function called 4 times

Register Storage Class: 

  • The Variables which are declared in this storage class are called register variables. 
  • These variables are stored in CPU registers. The value stored in CPU registers can be accessed very fast.
  • If the CPU register fails to keep the variables then the variables are automatically assumed as auto variables and they are stored in memory. 
  • CPU registers are very limited in number so we cannot declare more variables as register variables.
  • We cannot use the register storage class for all the data types present in CPU registers. 
  • The maximum size of the register will be up to 16 bits. We cannot define float or double variables in the register. 
  • Even if we try to store it does not show any error but these variables are converted into auto variables.
register int a;

Storage: CPU registers

Default value: garbage value

Scope: local to the block in which the variable is defined.

Life: till the control remains within the block in which the variable is defined.

C program using register

#include <stdio.h>
int main() {
    register int counter;  // Suggest 'counter' be stored in a register
    // Initialization is still necessary, even for register variables
    counter = 0; 
    // Loop to increment the counter
    for (int i = 0; i < 100000000; i++) { // A large number of iterations
        counter++; 
    }
    printf("Counter value: %d\n", counter);
    // Taking the address of a register variable is usually not allowed
    // int *ptr = &counter; // This would likely result in a compiler error or warning
    return 0;
}

Output:

Counter value: 100000000

What is the main difference between auto and static storage classes in C?

Featureautostatic
Default InitializationGarbage value0
LifetimeWithin the block where definedThroughout the program’s execution
ScopeLocal to the blockLocal to the block (if defined inside a function) or global (if defined outside any function)
Memory AllocationStackData segment (for global static) or stack (for local static)
Typical Use CasesTemporary variables within functionsVariables that need to retain their value across function calls

Advantages of storage classes in C:

1. Memory Management: Storage classes help optimize memory allocation by specifying where variables are stored (memory, CPU registers) and how long they persist. This is crucial for efficient resource utilization in embedded systems or large applications.

2. Scope Control: Storage classes define the visibility and accessibility of variables within different parts of the code. This allows for better organization, modularity, and avoids naming conflicts, especially in larger projects.

3. Default Value Initialization: Some storage classes provide default initialization of variables to 0 or garbage values. This can save coding effort and prevent unexpected behavior caused by uninitialized variables.

4. Variable Lifetime Management: Storage classes determine how long variables retain their values. This is essential for maintaining state across function calls (static variables) or limiting the lifespan of variables to specific blocks (automatic variables).

5. Code Optimization: By using appropriate storage classes, compilers can sometimes perform optimizations like storing frequently accessed variables in registers (register variables), leading to faster execution times.

Disadvantages of Storage Classes in C

  1. Complexity: The presence of multiple storage classes can increase code complexity, especially for beginners. Understanding the nuances of each class and their interactions requires careful consideration.
  2. Limited Scope for Dynamic Memory Allocation: Storage classes like ‘static’ allocate memory at compile time, limiting flexibility for dynamic memory allocation during runtime. This can be a constraint in scenarios where memory requirements change dynamically.
  3. Potential for Errors: Incorrect use of storage classes can lead to unexpected behavior and bugs. For instance, using ‘register’ for variables that the compiler cannot store in registers might result in reduced performance instead of optimization.
  4. Global Variables and Namespace Pollution: Overuse of ‘extern’ storage class for global variables can pollute the global namespace, potentially leading to naming conflicts and making code harder to maintain.
  5. Restricted Reusability: Functions using ‘static’ variables might not be easily reusable in different contexts due to the persistence of their state across calls. This can limit modularity and code portability.
  6. Performance Overhead (rare cases): In some cases, the use of storage classes might introduce slight performance overhead due to memory allocation and initialization processes. However, this overhead is often negligible in most practical scenarios.

Applications of storage classes in C programming:

auto:

  • Local Variables within Functions:  The most common use case for ‘auto’ is to declare temporary variables that are only needed within the scope of a function. This helps in managing memory efficiently, as these variables are automatically deallocated when the function exits.
  • Loop Counters and Iterators: When you need variables to control the iteration of loops, ‘auto’ is suitable. Their limited scope ensures they don’t interfere with variables outside the loop.

register:

  • Performance-Critical Variables: If you have variables that are frequently accessed within a function, declaring them as ‘register’ can suggest to the compiler to store them in CPU registers. This can potentially lead to faster access times and improved performance. However, use ‘register’ judiciously, as the number of available registers is limited.
  • Counters and Accumulators: In scenarios where you need to increment or update variables repeatedly (e.g., counters in loops), ‘register’ can be beneficial for optimization.

static:

  • Maintaining State Across Function Calls: When you need a variable to retain its value between function calls, ‘static’ is the ideal choice. This is often used for counters, flags, or variables that accumulate values over multiple invocations.
  • Global Variables with File Scope: Declaring ‘static’ variables outside any function gives them internal linkage, meaning they are only accessible within the same file. This helps in preventing naming conflicts and unintended side effects in larger projects.
  • Singleton Pattern Implementation: The ‘static’ keyword can be used to create variables that are initialized only once and persist throughout the program’s execution, effectively implementing the Singleton design pattern in C.

extern:

  • Sharing Variables Across Multiple Files: When you need to access a global variable defined in another file, ‘extern’ allows you to declare it in your current file. This enables code modularity and organization by separating variable definitions from their usage.
  • Library Functions and External Data: ‘extern’ is essential for utilizing functions and variables from external libraries or header files. It allows your code to reference and use these external resources seamlessly.

FAQs of Storage classes in C

  1. What are storage classes in C, and why are they important? 

    Storage classes in C determine the following attributes of a variable: 
    Scope: Where the variable is accessible (e.g., within a function, file, or globally). 
    Lifetime: How long the variable exists in memory (e.g., throughout the program’s execution or only during a function call). 
    Storage Location: Where the variable is stored in memory (e.g., in registers, on the stack, or in static memory).

  2. What are the four storage classes in C?

    The four main storage classes in C are:
    auto (Automatic): The default for local variables.
    static: Retains value between function calls and has file-level scope if declared outside a function.
    extern: Declares variables or functions defined in other files.
    register: Suggests to the compiler to store a variable in a CPU register for faster access.

  3. When should I use the register storage class?

    Use register when a variable (typically a loop counter or frequently used variable) is accessed intensively within a function.
    However, it’s just a hint to the compiler, and modern compilers are often good at making these optimizations automatically.

Scroll to Top