Search

4.3a — Scope, duration, and linkage summary

The concepts of scope, duration, and linkage cause a lot of confusion, so we’re going to take an extra lesson to summarize everything.

Scope summary

A identifier’s scope determines where it is accessible. An identifier that is out of scope can not be accessed.

  • Variables with block scope / local scope can only be accessed within the block in which they are declared. This includes:
    • Local variables
    • Function parameters
  • Variables with global scope / file scope can be accessed anywhere in the file. This includes:
    • Global variables

Duration summary

A variable’s duration determines when it is created and destroyed.

  • Variables with automatic duration are created at the point of definition, and destroyed when the block they are part of is exited. This includes:
    • Normal local variables
  • Variables with static duration are created when the program begins and destroyed when the program ends. This includes:
    • Global variables
    • Static local variables
  • Variables with dynamic duration are created and destroyed by programmer request. This includes:
    • Dynamically allocated variables (we’ll talk about these when we cover dynamic allocation in chapter 6)

Linkage summary

An identifier’s linkage determines whether multiple instances of an identifier refer to the same identifier or not.

  • Identifiers with no linkage mean the identifier only refers to itself. This includes:
    • Normal local variables
    • User-defined types, such as enums, typedefs, and classes declared inside a block (we’ll cover these in later lessons).
  • Identifiers with internal linkage can be accessed anywhere within the file it is declared. This includes:
    • Static global variables (initialized or uninitialized)
    • Const global variables
    • Static functions (we’ll cover these in chapter 7)
  • Identifiers with external linkage can be accessed anywhere within the file it is declared, or other files (via a forward declaration). This includes:
    • Normal functions
    • Non-const global variables (initialized or uninitialized)
    • Extern const global variables
    • User-defined types, such as enums, typedefs, and classes declared in the global scope (we’ll cover these in later lessons).

Identifiers with external linkage will cause a duplicate definition linker error if the definitions are compiled into more than one .cpp file.

There are a few things worth explicitly noting here. First, functions are extern by default, and can be made internal by using the static keyword.

Second, astute readers may note that global types have external linkage, but their definitions don’t cause a linker error when included in multiple files. This is because types, templates, and extern inline functions have an exemption that allows them to be defined in more than one file, so long as the definitions are identical. Otherwise, they wouldn’t be of much use.

Variable scope, duration, and linkage summary

Because variables have scope, duration, and linkage, let’s summarize in a chart:

Type Example Scope Duration Linkage Notes
Local variable int x; Block scope Automatic duration No linkage
Static local variable static int s_x; Block scope Static duration No linkage
Dynamic variable int *x = new int; Block scope Dynamic duration No linkage
Function parameter void foo(int x) Block scope Automatic duration No linkage
External non-const global variable int g_x; File scope Static duration External linkage Initialized or uninitialized
Internal non-const global variable static int g_x; File scope Static duration Internal linkage Initialized or uninitialized
Internal const global variable const int g_x(1); File scope Static duration Internal linkage Must be initialized
External const global variable extern const int g_x(1); File scope Static duration External linkage Must be initialized

Forward declaration summary

You can use a forward declaration to access a function or variable in another file:

Type Example Notes
Function forward declaration void foo(int x); Prototype only, no function body
Non-const global variable forward declaration extern int g_x; Must be uninitialized
Const global variable forward declaration extern const int g_x; Must be uninitialized
4.3b -- Namespaces
Index
4.3 -- Static duration variables

29 comments to 4.3a — Scope, duration, and linkage summary

  • Curiosity

    When We Use main function in multiple files in a project it produces a linker error,
    is it due to the multiple definition of main function ? I am asking because my code::blocks linker produces an error when i try to do so !

    Second, astute readers may note that global types have external linkage, but their definitions don’t cause a linker error when included in multiple files. This is because types, templates, and extern inline functions have an exemption that allows them to be defined in more than one file, so long as the definitions are identical. Otherwise, they wouldn’t be of much use.
    Explain Me this too using an example !

    • Alex

      1) A program is only allowed to have one main() function.

      2) Define an enum in a header file, then include that header file into two different .cpp files. Each .cpp file will get a copy of the enum definition, but this will not cause a linker error.

  • James Ray

    "This is because types, templates, and extern inline functions have an exemption that allows them to be defined in more than one file, so long as the definitions are identical." What is the point of allowing them to be defined them more than once, provided that the definitions are identical? Just so you don’t get a linker error and thus avoid crashing the program? It seems like it is best to avoid defining them more than once at all. Is there any cases where it would be useful to define them more than once (with the same definition)?

    Maybe also change the example of the static local variable in the table to int s_x?

    • James Ray

      Looks like the next lesson covers why it is not necessary to use std::cout every time with cout, so long as using std::cout is used in the first instance, or using namespace std is used (although it’s best to avoid doing this.

    • Alex

      For this conversation, let’s be more precise about how we use the term “define”.

      You should only define your types in one place (most often, in a header file) -- redundant code is bad. However, in any program of sufficient complexity, that header file will be #included into multiple .cpp files. This propagates that type definition into multiple code files, each of which will be independently compiled and linked. Without this exemption, the linker would note that a definition has been defined (actually propagated) in multiple places, and flag an error.

      So basically, this exemption allows us to propagate types, templates, and inline function definitions from a single header out to multiple code files, where they can be used.

      Also, updated the static local variable per your suggestion. Thanks!

  • Varun

    Give the man a knighthood.

  • Nguyen

    Hi Alex,

    I don’t understand the second row (Static local variable) in the chart.

    Example:  static int x;
    Scope:    Block scope
    Duration: Static duration
    Linkage:  No linkage
    Note:  

    I believe "Static Local Variable" is covered in the very last section 4.3.  

    I think "Static Local Variable" has Static duration if I both define a variable AND give it an initial value in the same step(for example: static int x = 1;).  

    In the above example, x is not initialized.  I am not sure if x has Static or automatic duration? If x has static duration then why the output of the following code is different from another?

    #include <iostream>

    void incrementAndPrint()
    {
        using namespace std;
        static int s_value = 0; // static duration variable initialized
        ++s_value;
        cout << s_value << endl;
    }

    int main()
    {
        incrementAndPrint();
        incrementAndPrint();
        incrementAndPrint();

        return 0;    
    }

    Which outputs:

    1
    2
    3

    Declaring a static duration variable, then assigning a literal to it:

    #include <iostream>

    void incrementAndPrint()
    {
        using namespace std;
        static int s_value; // static duration variable declared
        s_value = 0; // static duration variable assigned
        ++s_value;
        cout << s_value << endl;
    }

    int main()
    {
        incrementAndPrint();
        incrementAndPrint();
        incrementAndPrint();

        return 0;    
    }

    Which outputs:

    1
    1
    1

    • Alex

      Static variables have static duration regardless of whether you initialize them or not. In your example, you’re not initializing the static (which would only happen once, when the static is created). Instead, you’re assigning a value to the static variable, which happens every time the function runs. So even though your static s_value is keeping its value between function calls, you’re resetting it back to 0 via assignment every function call.

      This is why we typically initialize static variables, not assign values to them.

  • nikos-13

    " (initialized or uninitialized) "

    Why do you use this prenthesis

  • John

    Can you please explain how "Extern const global variable"  has external linkage ? can we access any variable defined as const in other file without using namespace?

    a.cxx:
    extern const int a(5);

    b.cxx:

    extern const int a;
    int main(){
        std::cout << a << std::endl;
    }

    It gives an error as “b.cxx:(.text+0x6): undefined reference to `a’ “

  • Matt

    In section "Duration summary", the listings for automatic duration and static duration (local variables) should be updated to reflect that the variables are created during definition, not when the block is entered.

  • kris

    This is very helpful. Thank you

  • Thanks Alex,
    I need to clear one more thing, Consider I have 2 Task  and I called a common function from both the task which having a static local variable , So from one task I am accessing and set one value to that static variable, and through another task I read that value. So In both case am accessing the same local static variable. My doubt is ,am accessing the same memory ? able to consider that variable as a shared variable or shared memory?

    • Alex

      In both cases, you’re accessing the same local static variable, which uses the same memory. It’s not really shared memory -- it’s just a variable that you can access whenever you’re inside the function (doesn’t matter which function it was called from).

      • Hi Alex

        Why it’s not shared memory? As per my knowledge shared memory is the memory in which a common memory get accessed from 2 different task, is it correct ?  Would you please give me the definition of Shared memory?

        • Alex

          Maybe I’m misunderstanding what you mean by task. If by task you mean “process” or “thread” (or anything else that can run in parallel), then yes, the memory would be shared.

          • Yes, I meant Task as two separate Process that may or may not be run parallel.

            Now everything is clear

            Thanks Alex.

            The effort you put in this site is really worth for learner

  • Hi Alex,
    Thanks a lot for the replay

    I tried indirectly, Like address of a static local variable assigned to a global pointer and deferred at another function. Compiler not showing any error and I am getting the expected result as well. As per my knowledge the lime time of the static local variable till up to the end of the program ,  is it correct? then why can’t access the local static variable outside that function(indirectly)? is any risk involved in this way like data overwriting?

    • Alex

      Yes, the lifetime of a local static variable is until the end of the program. But the scope of a local static variable is still only within the function in which it is declared, the same as a local non-static variable. The scope governs where you can access the variable, which is why you can’t use it directly outside the function.

      You can access the variable outside the function indirectly (via a pointer or reference), but even though you can do this, it’s not advised.

  • Hi, I have one doubt.
    is it possible to access a static local variable in a function from the main function. if it possible to access, then that data is safe or not?

    • Alex

      No, it is not possible (at least not directly). Static local variables are only visible within the function in which they are declared.

  • Robert Hannah

    Wow. I was literally just about to write some kind of summary like this to supplement notes I’ve taken from your website. Thanks! I’ve been using this site for years: Perhaps the best non-book resource that there is on C++.

  • Got cleared all of my former doubts…Bro Thankyou so much for this awsome site…

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter