Lesson 38 of 60 – Storage Classes in C
63%

Storage Classes in C

Storage classes in C help define the scope, lifetime, visibility, and storage-related properties of variables and functions. They tell the compiler how a variable can be accessed and how long its stored value is maintained.

Note: The commonly discussed storage-class specifiers in C are auto, register, static, and extern.

1. What is a Storage Class?

A storage class specifies certain properties of a variable, such as its scope and lifetime.

int number = 10;

Variables can have different storage characteristics depending on where and how they are declared.

2. Main Storage-Class Specifiers

The commonly studied storage-class specifiers are:

  • auto
  • register
  • static
  • extern

Each one has a different purpose and behavior.

3. Scope and Lifetime

Two important concepts when studying storage classes are scope and lifetime.

  • Scope: The part of the program where a name can be accessed.
  • Lifetime: The period during program execution for which an object exists.

Storage-class specifiers help determine these properties.

4. The auto Storage Class

The auto storage-class specifier is associated with local variables declared inside a block.

int main()
{
    auto int number = 10;

    printf("%d", number);

    return 0;
}

The variable exists during execution of the block in which it is declared.

5. auto is Usually Omitted

For ordinary local variables, the auto keyword is normally not written explicitly.

int main()
{
    int number = 10;

    printf("%d", number);

    return 0;
}

The declaration above is an ordinary automatic local variable.

6. Local Variable with auto

void display()
{
    auto int value = 50;

    printf("%d", value);
}

int main()
{
    display();

    return 0;
}

The variable value is local to the function and its lifetime is associated with execution of that function invocation.

7. The register Storage Class

The register specifier requests that a variable be stored in a processor register when practical.

int main()
{
    register int count = 10;

    printf("%d", count);

    return 0;
}

The compiler decides whether the request can actually be honored.

8. register Variables

Register storage can be useful for variables that are accessed frequently, but modern compilers generally make their own optimization decisions.

register int counter;

for (counter = 0; counter < 10; counter++)
{
    printf("%d ", counter);
}

The register keyword should not be treated as a guarantee that the variable will be stored in a CPU register.

9. Address of register Variable

A program should not use the address-of operator & on an object declared with the register storage-class specifier.

register int number = 10;

/* &number is not allowed */

This is one reason register differs from an ordinary local variable declaration.

10. The static Storage Class

The static specifier can be used with variables at block scope or file scope.

void display()
{
    static int count = 0;

    count++;

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

A static local variable retains its stored value between function calls.

11. Static Local Variable

#include <stdio.h>

void counter()
{
    static int count = 0;

    count++;

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

int main()
{
    counter();
    counter();
    counter();

    return 0;
}

Output:

1
2
3

The variable retains its value between calls.

12. Why Static Local Variables Are Useful

A static local variable is useful when a function needs to remember information between calls without exposing that variable outside the function.

void visits()
{
    static int count = 0;

    count++;

    printf("Function called %d times\n", count);
}

13. Static Variable is Initialized Once

void test()
{
    static int number = 10;

    printf("%d\n", number);

    number++;
}

The initialization of the static local variable occurs once. Later calls continue using its existing stored value.

14. Static Global Variable

At file scope, a variable declared with static has internal linkage. This means its name is limited to the current source file.

static int total = 100;

Other source files cannot refer to this file-scope variable using the same external name.

15. Static and Lifetime

A static object's lifetime lasts for the entire execution of the program, even when the variable is declared inside a function.

void display()
{
    static int number = 5;

    number++;

    printf("%d\n", number);
}

The variable remains available for future calls to the function.

16. The extern Storage Class

The extern keyword is commonly used to declare an object that is defined elsewhere, often in another source file.

extern int total;

This declaration tells the compiler that the definition of total is provided elsewhere.

17. extern with a Global Variable

#include <stdio.h>

int total = 100;

void display()
{
    extern int total;

    printf("%d", total);
}

int main()
{
    display();

    return 0;
}

The extern declaration refers to the existing definition of total.

18. extern Across Multiple Files

Suppose one source file contains the definition:

int total = 500;

Another source file can declare it with:

extern int total;

When the program is linked, both source files can refer to the same object, provided the definition is available to the program.

19. Difference Between static and extern

static extern
Can give a file-scope object internal linkage. Can declare an object defined elsewhere.
Static local variables retain their values between calls. Commonly used to refer to an externally defined object.
Can limit a file-scope name to one source file. Can allow a declaration to refer to an external definition.

20. Scope of Local Variables

void test()
{
    int number = 10;

    printf("%d", number);
}

The variable number can be accessed only within its block. It cannot be directly accessed from another function.

21. Automatic Variable Lifetime

void test()
{
    int number = 10;

    printf("%d", number);
}

For an ordinary local automatic variable, the object's lifetime is tied to execution of the block in which it is declared.

22. Comparing Automatic and Static Local Variables

Automatic local variable:

void test()
{
    int count = 0;

    count++;

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

Calling this function repeatedly starts count from its initial value for each invocation.

Static local variable:

void test()
{
    static int count = 0;

    count++;

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

The static variable retains its value between calls.

23. Default Initialization of Static Variables

Objects with static storage duration that are not explicitly initialized are initialized to zero.

void test()
{
    static int number;

    printf("%d", number);
}

The value of number starts as 0.

24. Choosing a Storage Class

  • Use ordinary local variables for normal local data.
  • Use static when a local variable needs to retain its value between calls.
  • Use file-scope static when a file-level object should have internal linkage.
  • Use extern when referring to an object defined elsewhere.
  • Use register only when appropriate; modern compilers usually handle optimization themselves.

25. Static Counter Example

#include <stdio.h>

void counter()
{
    static int count = 0;

    count++;

    printf("Count = %d\n", count);
}

int main()
{
    counter();
    counter();
    counter();
    counter();

    return 0;
}

Output:

Count = 1
Count = 2
Count = 3
Count = 4

26. Common Storage Class Mistakes

  • Thinking register guarantees CPU-register storage.
  • Expecting an automatic local variable to retain its value between function calls.
  • Confusing the scope of a variable with its lifetime.
  • Using extern without providing a corresponding definition where required.
  • Assuming file-scope static variables can be accessed from another source file.

27. Storage Class Comparison

Specifier Common Use Important Property
auto Local variables Automatic storage duration
register Local variables Requests register storage
static Local/file-scope objects Retains lifetime; file-scope static gives internal linkage
extern External declarations Refers to an object defined elsewhere

28. Complete Static Counter Program

#include <stdio.h>

void visit()
{
    static int count = 0;

    count++;

    printf("Function called %d times\n", count);
}

int main()
{
    visit();
    visit();
    visit();

    return 0;
}

The static variable remembers its previous value every time the function is called.

29. Storage Classes and Functions

Storage-class concepts also apply to functions. For example, a function defined with static at file scope has internal linkage and can be called only from that source file.

static void display()
{
    printf("Hello");
}

This is useful when a helper function should remain private to one source file.

30. Practice Programs on Storage Classes

Practice the following programs:

  1. Create a local automatic variable and display its value.
  2. Create a static counter function and call it multiple times.
  3. Compare an automatic local variable with a static local variable.
  4. Create a file-scope static variable.
  5. Create a function with a static file-scope helper function.
  6. Use an extern declaration with a global variable.
  7. Create a program demonstrating static variable initialization.
  8. Create a counter that remembers its value between function calls.
  9. Write a program using multiple functions and a file-scope static helper.
  10. Explain the difference between auto, register, static, and extern.

📌 Key Points

  • Storage classes describe important properties of variables and functions.
  • auto is associated with ordinary local automatic variables.
  • register requests register storage but does not guarantee it.
  • static local variables retain their values between function calls.
  • File-scope static gives internal linkage.
  • extern is commonly used to declare an object defined elsewhere.
  • Scope describes where a name can be accessed.
  • Lifetime describes how long an object exists.
  • Static-storage-duration objects exist throughout program execution.
  • Choosing the appropriate storage class helps organize C programs.

🧠 Quick Quiz

Question: Which storage-class specifier allows a local variable to retain its value between function calls?