6.6 — Internal linkage

In lesson 6.3 -- Local variables, we said, “An identifier’s linkage determines whether other declarations of that name refer to the same object or not”, and we discussed how local variables have no linkage.

Global variable and functions identifiers can have either internal linkage or external linkage. We’ll cover the internal linkage case in this lesson, and the external linkage case in lesson 6.7 -- External linkage.

An identifier with internal linkage can be seen and used within a single file, but it is not accessible from other files (that is, it is not exposed to the linker). This means that if two files have identically named identifiers with internal linkage, those identifiers will be treated as independent.

Global variables with internal linkage

Global variables with internal linkage are sometimes called internal variables.

To make a non-constant global variable internal, we use the static keyword.

Const and constexpr global variables have internal linkage by default (and thus don’t need the static keyword -- if it is used, it will be ignored).

Here’s an example of multiple files using internal variables:



This program prints:


Because g_x is internal to each file, main.cpp has no idea that a.cpp also has a variable named g_x (and vice versa).

For advanced readers

The use of the static keyword above is an example of a storage class specifier, which sets both the name’s linkage and its storage duration (but not its scope). The most commonly used storage class specifiers are static, extern, and mutable. The term storage class specifier is mostly used in technical documentations.

The one-definition rule and internal linkage

In lesson 2.6 -- Forward declarations and definitions, we noted that the one-definition rule says that an object or function can’t have more than one definition, either within a file or a program.

However, it’s worth noting that internal objects (and functions) that are defined in different files are considered to be independent entities (even if their names and types are identical), so there is no violation of the one-definition rule. Each internal object only has one definition.

Functions with internal linkage

Because linkage is a property of an identifier (not of a variable), function identifiers have the same linkage property that variable identifiers do. Functions default to external linkage (which we’ll cover in the next lesson), but can be set to internal linkage via the static keyword:



This program won’t link, because function add is not accessible outside of add.cpp.

Quick Summary

We provide a comprehensive summary in lesson 6.11 -- Scope, duration, and linkage summary.

6.7 -- External linkage
6.5 -- Variable shadowing (name hiding)

42 comments to 6.6 — Internal linkage

  • james

    Hi, I'm a little confused about the global variable and static global variable. For example,


    What are the differences between them? From 6.4, the global variable enjoys the file scope, which means that it is already accessible in the entire file. Besides, the global variable can already survive during the entire program. So why do we still need the "static" keyword? Thank you!

    • nascardriver

      The `static` variable can only be accessed in the file that it was declared in. The non-`static` variable can be accessed by all files (If they declare it as `extern`).

  • Robert Warner

    Why does this not compile? main.cpp does not see the variable in a.cpp.

    int g_x{ 2 };

    #include <iostream>
    int main()
        std::cout << g_x << '\n';

        return 0;

  • J34NP3T3R

    Clarification :

    if i dont use STATIC on a global non-constant variable it can be referenced in another file ?

    if i have


       int g_x{5};


       std::cout << g_x ;

    i can see the variable in main.cpp ?

  • J34NP3T3R


    if we wanted a constant variable that is global with external linkage how do we do it ?

    since all constant variables are internal.

  • Patrick

    Why do const objects have internal linkage by default?

  • Alexandre Silva

    Should we favor the use of static keyword for functions within a file as much as possible for a bigger program? Is it considered good practice?

  • Where should the `static` keyword go - header file, .cpp file or both? I ask this because I noticed that the compiler (i.e. Visual Studio) doesn't seem care.

    • John

      If I've understood correctly, you should use the static keyword both for the definition in the .cpp file as well as the declaration in the .h file. This should ensure that if you #include your .h file, the linker doesn't complain about getting a mismatch in declaration and definition when you run your program. I am no expert though, so it's probably best to just try it out!

    • nascardriver

      You don't separate `static` variables or functions into header and source files. `static` is used to give these entities internal linkage, ie. make them accessible only in the current _source file_. If you want something to be accessible across files, it must have external linkage (and not be `static`) or be `inline` and have internal linkage.

  • an old man and c++

  • sergey

    Thanks for this tutorial, very well explained!
    Regarding "The one-definition rule and internal linkage" part.
    Specifically this statement -
    "we noted that the one-definition rule says that an object or function can’t have more than one definition, either within a file or a program."
    But what about "variable shadowing", isn't that more than one definition in a single file (program)?

  • Jeff

    Under the section titled Functions with Internal Linkage, the example given confuses me a bit.  Shouldn't the code in main.cpp include the header file add.h?  Otherwise, how does main.cpp potentially see anything in that header file?  I know the point of the exercise is to make function add() static (internal) instead of the default external.  Is there another way that main.cpp was "seeing" the add.cpp file without #including the code.  I hope I'm making sense here....

    • nascardriver

      You don't _need_ headers. There's no connection between a header and its source file. All a header does is provide forward declarations for the definitions in the source file. In the example you're referring to, we manually forward declared `add` in main.cpp. A header wouldn't have done anything different.

  • papapius

    I saw "static" written after the "const" keyword. Like that:

    Has this the same meaning with "static" written before "const"? Like that:

    ps: I know that const variable has internal linkage by default, and no need for static anyway.

  • saylee

    I am just trying to understand the difference between "int x" and "static int x" so i wrote the following code-


          int x = 8;


        #include <iostream>
        #include "Const.cpp"

        int main()
          std::cout << x << "\n";

    In this case i get the following error
    Error    LNK1169    one or more multiply defined symbols found

    But if I write the following-    


          static int x = 8;


        #include <iostream>
        #include "Const.cpp"

        int main()
          std::cout << x << "\n";

    Then it compiles.

    This voilates "Internal global variables definitions"

    Can you please help me with this?

  • Monika

    Hello! I am loving these tutorials probably way more than I should lol XD . No seriously they helped me understand c++ better than I ever imagined. Thank you Alex and Nascardriver for the effort you put in these tutorials.
    I wanted to ask if anyone knows a website for teaching HTML/CSS or python, I mean a website or an app or a youtube channel (it doesn't matter) that teaches those languages not just the syntax but also how and why those languages are the way they are and if possible they also show you the best practices and what not.
    If there isn't though how can I know those stuff on my own? I mean the best practices and what to do and what not to do...
    It's honestly sad I see no tutorials as good as yours guys that really focuses on the reader understanding the fundamentals and following best practices :(
    Anyway enough with my rambling, please help if you know anything :)

  • sami

    I have two questions:

    1) "The most commonly used storage class specifier values are static, extern, and mutable."

    I am not an advanced learner, but I am curious to know about it : does that sentence mean if we use any of those keyword with identifiers (static, or extern or mutable), we refer to them as "storage class specifier"?

    2) Is this use of 'static' here different from 'static' used for instance variables of a class in Object Oriented?

    • nascardriver

      The meaning of `static` depends on the context. It can be used as a storage specifier, to cause internal linkage, and to declare instance-less members. You've seen the first 2 already, we show the third version later.

  • Tepy

    "Because linkage is a property of an identifier (not of a variable), functions have the same linkage property that variables do. "

    Should this be rephrased to:
    "Because linkage is a property of an identifier (not of a variable), functions have the same linkage property that identifiers do."

  • Abraxasknister

    How does this interact with #include? For example if I have

    would then mps and mpss each utilize their own ever lasting copy of g so that the purpose of having that g centralised is defeated because it's stored twice? (I'm guessing that the better solution would be to have it in a constants namespace).

    • nascardriver

      Each get their own `g`. Making `g` `inline` solves this.

      • AbraxasKnister

        It's though technically different than having one g with external linkage, right? The effect of using inline is that occurrences of g in mps and mpss are treated at compile time as if they were the literal "9.8". So in that case there's never even allocated memory for the double g.

        • nascardriver

          Nope, "inline" is a misleading name. It doesn't mean that `inline` functions/variables get inlined (though, they might). `inline` variables don't have to be `const` either, you can reassign values during run-time.
          `constexpr` variables are closer to what you've explained. Their value can be computed at compile-time, so it's likely they disappear during compilation.

          • AbraxasKnister

            Thanks for the clarification. I looked up the inline specifier and it looks like this: if you declare something  `inline constexpr` it's given external linkage and the permission to multiple definitions. Thus it may or may not be optimized away due to either of `inline` or `constexpr` but if it is not optimized away then at least it's only allocated once. Pre cpp17 you could either (as said in the lecture) declare it as const and external and define it once (where it would most surely wouldn't get optimized away and allocated once) or define it multiple times as internal and constexpr (where it most surely would be optimized away but allocated multiple times if the optimisation failed). I only was unsure if it's given external linkage in the case of `inline constexpr` declaration by default and indeed: "Inline const variables at namespace scope have external linkage by default (unlike the non-inline non-volatile const-qualified variables)". Says the reference. Quite possible you said that in the lecture already and I missed it.

  • kavin

    I was thinking that till now that warnings are actually legit errors in main code that program would ignore to compile if "Treat warnings as errors" was disabled. Thanks for clearing my doubt @nascardriver

  • kavin

    Under "Functions with internal linkage", if i add
    int add(int x, int y)
        return x - y;
    to main.cpp and remove int add(int x, int y); then i get this error.

    Source.cpp(1,12): error C2220: the following warning is treated as an error
    Source.cpp(1,12): warning C4505: 'add': unreferenced local function has been removed

    why is that? since add.cpp has a static function, the program should auto ignore the function in add.cpp  and compile without any problem right ? But it behaves differently here.

    • nascardriver

      You're not getting an error as a violation of a language rule.
      You're getting an error because you got a warning and your treating warnings as errors.
      You're getting a warning as a friendly reminder from the compiler that you wrote a function but you're never using it (`add` in "add.cpp").

      The code is fine, but you made a mistake, and you told your compiler not to let you make mistakes. If you want to compile the code anyway, you can temporarily disable "Treat warnings as errors" (or similar) in your project settings.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]