Storage Classes

Recall that a variable has a name, a type and stores a value of the particular type. It also have other attributes such as storage duration, scope and linkage, which is either set implicitly, or via so-called storage class specifiers such as auto (automatic storage allocation/deallocation. C++11 reassigns this keyword to mean automatic derived type), register, static, extern, mutable and thread_local (added in C++11); or CV-qualifiers: const and volatile (CV stands for constant-volatile).

Storage Duration - Automatic, Static and Dynamic

The storage duration (or storage class) determines the duration of a variable, i.e., when it is created and when it is destroyed. They are 3 types of storage durations:

Automatic storage duration: Variables declared inside a function (including function parameters) or block have automatic storage duration. They are created when the program enters the function (or the block) in which they are defined, and destroyed (memory is deallocated and freed) when the program leaves the function (or the block). They are called automatic as they are managed (created/destroyed) automatically without programmer's explicit actions. They will be created/destroyed repeatably as the program enters and leaves the function (or block).
Static storage duration: Variables declared outside all functions, or inside a function with static specifier have static storage duration. The term static means that (a) the variable is created when the program begins and destroyed when the program exits, i.e., it exists for the entire duration of the program; (b) the variable retains its memory and contents throughout the entire execution.
Dynamic storage duration: Dynamic storage are managed by programmer explicitly (instead of automatically). Storage (on the heap) is allocated via new operator and persists until they are freed via the delete operator.
Compiler typically allocates 3 chunks of storage for static variables, automatic variables, and dynamically allocated variables, respectively.

Scope - Local or Global

The scope of a variable determines which parts of the program can reference the variable, i.e., the visibility. Some variables can be referenced throughout the program (file-scope or global-scope); while others can only be referenced in a limited part of the program (block-scope or local-scope). For example, a local automatic variable defined inside a function (or a block) is visible by that function (or block), and not outside the function (or block).

There are two scopes:

➦ A variable having local scope (or block scope) is visible only inside the block.
➦ A variable having global scope (or file scope) is visible throughout the file.

Linkage - Internal or External

A C/C++ application may consist of many source files (or translational units). The linkage of a variable determines how a variable is shared by different files. A variable with external linkage can be shared by other source files; while a variable with internal linkage can only be used in the file that it is defined. That is, external linkage extends the file-scope to other source files.

In summary, with linkage, there are 3 combinations of scopes/linkages:

➦block-scope (or local-scope) with no linkage,
➦file-scope (or global scope) with internal linkage,
➦file-scope (or global scope) with external linkage.

Take note that a variable might exist in memory (determined by its storage duration) but not visible by a certain part of the program (determined by its scope and linkage). For examples, a local variable created within a function still exists when the function calls another function, but it is not visible by the second function. A static variable declared inside a function exists throughout the program duration, but visible only by that function. A static variable with internal linkage exists throughout the program duration, but visible only to the file in which it is defined.

 Automatic Local Variables ("auto" Specifier)

Variables defined inside a function (block) and function parameters are "auto", by default. They have automatic storage duration, i.e., they are created when the program enters the function (block) and destroyed when the program leaves the function (block). They have local scope (i.e., can be used within the function or block immediately after they are declared) and no linkage (i.e., either internal or external linkage).

Automatic storage is used to converse memory, as these variables does not exist throughout the entire program, but created when needed (and destroyed).

You can use the auto specifier to explicitly specify automatic storage class for a variable. However, it is rarely used as auto is the default for local variables. In C++11, the keyword "auto" is assigned a new meaning to indicates automatic type deduction. The old meaning of automatic storage class is no longer valid in C++11.
Register Automatic Variables ("register" Specifier)
You can use the "register" specifier to suggest to the compiler to put an automatic variable in a register for faster access. This is often unnecessary, as an optimizing compiler can do this automatically.

 Static Variables ("static" Specifier)

As mentioned, a static variable:
➦is allocated when the execution begins and lasts for the entire duration of the program;
➦retains its memory and contents throughout the program execution. An static variable declared inside a function retains its value even when the function exits.
Static variables are initialized to zero (all its bits set to 0), if no initial values are provided. All elements of static array and structures are initialized to zero too. On the other hand, automatic local variables are not initialized.

Static variables are allocated at fixed memory locations (instead of function stack) as they last for the entire program duration.

Static variables has three types of linkage:


  • external: global static variables visible in other source files - defined outside all functions.
  • internal: global static file-scope variables visible in the file that it is defined - defined outside all functions with keyword static.
  • no linkage: local static variable visible within a function or block for which it is defined -defined inside a function with keyword static.

Static class members
A static class member (data or function) belongs to the class, instead of instances. It can be referenced directly from the class, without creating instances, via Classname::staticMemberName. A staticdata member retains its value throughout the program execution.

 External Variables ("extern" Specifier)

The extern specifies linkage to another source file. It tells the compiler that the identifier is defined in another (external) source file.

CV-Qualifiers (const and volatile) and mutable

The "const" qualifier indicates that the content of the storage location shall not be changed after initialized.

The "volatile" qualifier indicates that the content of the storage location could be altered outside your program, e.g., by an external hardware. This qualifier is needed to tell compiler not to optimize this particular location (e.g., not to store in register, not to re-order the statement, or collapse multiple statements).

The mutable specifier can be used in struct or class to indicate that a particular data member is modifiable even though the instance is declared const.

"const" Global Variables
By default, a global variable (defined outside all functions) has external linkage. However, const global variable has internal linkage (as if static specifier is used). As the result, you can place all const global variables in a header file, and include the header in all the source files. To set a const global variable to external linkage, include "extern" specifier.

Function and Linkage
So far, we were discussing about variables. By default, functions have duration of the entire program, and external linkage (can be shared across file).

You use use the "static" specifier to confine the function to internal linkage (accessible in this file only). The "one definition only" rule applies to all non-inline functions. That is, there is only one function definition. Each file shall have the function prototype (declaration). Since inline functions are often placed in the header, which will be included in all file, the "one definition rule" makes an exception. However, all copies of inline function shall be identical.

If a function is declared static in its prototype, the C++ compiler/linker search the current file only for the function definition. Otherwise, C++ compiler/linker searches all the program files. It issues an error if it finds more than one definitions. If the function is not found in all the program files, it then searches the libraries.

extern "C" vs. extern "C++"
Many C++ compilers use a so-called "name mangling scheme" to support function overloading (i.e., many versions for the same function name differentiated by their parameter list). You can use keyword extern to indicate the naming protocol of the function.

Comments

Popular posts from this blog

Covid-19 Analysis and Visualization using Plotly Express

Artificial Intelligence (Problem Solving)

Linear Regression