SrcForge

Lesson 19

Storage Classes

Covers storage duration, scope, linkage, and the auto, register, static, and extern keywords.

Lesson content

What are storage classes in C++?

A storage class specifies the properties of a variable or function.

  • Where it is stored in memory
  • How long it exists during program execution
  • Where it can be accessed
  • Whether it can be shared across multiple files

Storage classes help the compiler manage variables efficiently and determine their behavior throughout a program.

Why do storage classes exist?

Programs often require variables with different lifetimes.

  • A temporary variable should exist only while a function executes
  • A counter may need to retain its value between function calls
  • A global variable may need to be shared across multiple source files

Real-world use cases

  • Function call counters
  • Embedded systems
  • Game development
  • Large software projects
  • Multi-file applications
  • System programming
  • Device drivers
  • Performance optimization

Core properties

Property              | Description
--------------------- | -----------------------------------------
Storage Duration      | How long the variable exists in memory
Scope                 | Where the variable can be accessed
Linkage               | Whether the variable can be shared across files
Default Initial Value | Initial value assigned if not explicitly set

Types of storage classes

Storage Class | Purpose
------------- | ----------------------------------------------
auto          | Default storage class for local variables
register      | Suggests storing a variable in a CPU register
static        | Preserves a variable's value throughout execution
extern        | Declares a variable defined in another source file

auto storage class

auto is the default storage class for local variables. Since C++11, it's primarily used for automatic type deduction, making the old storage-class usage largely obsolete.

auto int number = 10;
  • Local scope
  • Automatic storage duration
  • Destroyed when the block ends
int age = 25;
// age is automatically an auto variable

register storage class

register suggests that a variable should be stored in a CPU register for faster access.

register int counter;
  • Local scope
  • Automatic lifetime
  • Compiler may ignore the request
  • Cannot reliably take the address of a register variable

Since C++17, register is deprecated and has no practical effect in modern C++. Compilers automatically optimize variable placement.

static storage class

static gives a variable static storage duration.

  • Initialized only once
  • Retains its value between function calls
  • Exists until the program ends
static int count = 0;
  • Initialized only once
  • Lifetime lasts until program termination
  • Scope remains local if declared inside a function

extern storage class

extern declares a variable that is defined elsewhere, typically in another source file.

extern int total;
  • Global scope
  • Static storage duration
  • Used in multi-file programs
  • Avoids creating duplicate global variables

Storage class comparison

Feature             | auto    | register | static           | extern
------------------- | ------- | -------- | ----------------- | ---------------
Scope               | Local   | Local    | Local/Global       | Global
Lifetime            | Block   | Block    | Entire program     | Entire program
Default Value       | Garbage | Garbage  | 0                  | 0
Shared Across Files | No      | No       | Global only        | Yes

Example 1: Automatic variable

#include <iostream>
using namespace std;

int main()
{
    int number = 10;

    cout << number;

    return 0;
}

Example 2: Static local variable

#include <iostream>
using namespace std;

void counter()
{
    static int count = 0;

    count++;

    cout << count << '\n';
}

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

    return 0;
}

// Output:
// 1
// 2
// 3

Example 3: Register variable

#include <iostream>
using namespace std;

int main()
{
    register int i = 100;

    cout << i;

    return 0;
}

// Note: Modern compilers generally ignore the register keyword.

Example 4: Global static variable

#include <iostream>
using namespace std;

static int counter = 10;

int main()
{
    cout << counter;

    return 0;
}

Example 5: Using extern

// File: main.cpp
#include <iostream>
using namespace std;

extern int total;

int main()
{
    cout << total;

    return 0;
}

// File: data.cpp
int total = 500;

Common mistakes and pitfalls

  • Using register for optimization. Fix: let the compiler optimize automatically
  • Overusing global static variables. Fix: limit their use
  • Forgetting that static retains values. Fix: reset manually if needed
  • Using extern without a matching definition. Fix: define the variable in one source file
  • Assuming auto is still a storage-class keyword. Fix: use auto mainly for type deduction
// Wrong
void display()
{
    int count = 0;

    count++;

    cout << count;
}
// Output is always: 1
// Correct
void display()
{
    static int count = 0;

    count++;

    cout << count;
}
// Output after three calls: 1 2 3

Best practices

  • Prefer local variables over global variables whenever possible
  • Use static only when persistent state is genuinely needed
  • Avoid using register in modern C++
  • Use extern only for variables that must be shared across source files
  • Prefer auto for type deduction, especially with complex types
  • Minimize global state to improve maintainability and testability

When not to use this

  • register: deprecated and ignored by modern compilers
  • static: avoid for shared mutable state unless necessary
  • extern: avoid excessive global variables; prefer classes or namespaces
  • auto: avoid when the deduced type is not obvious

Summary

  • Storage classes define a variable's lifetime, scope, storage duration, and linkage
  • auto is the default for local variables and is now used for type deduction
  • register was intended for faster access but is deprecated
  • static variables retain their values throughout the program's lifetime
  • extern allows variables to be shared across multiple source files
  • Understanding storage classes helps write efficient, organized, maintainable C++

Frequently asked questions

What is a storage class in C++?

Defines how a variable is stored in memory, how long it exists, where it can be accessed, and whether it can be shared across source files.

What is the difference between static and extern?

A static variable has static storage duration and internal linkage when declared globally, while extern refers to a global variable defined elsewhere with external linkage.

Is the register keyword still useful?

No. Since C++17, register is deprecated, and modern compilers automatically optimize variable placement.

What is the modern use of auto in C++?

auto is primarily used for type deduction, letting the compiler determine a variable's type automatically.

When should I use a static local variable?

Use it when a function needs to remember a value between multiple calls, such as counting executions.