Search

6.4 — Introduction to global variables

In lesson 6.3 -- Local variables, we covered that local variables are variables defined inside a function (or function parameters). Local variables have block scope (are only visible within the block they are declared in), and have automatic duration (they are created at the point of definition and destroyed when the block is exited).

In C++, variables can also be declared outside of a function. Such variables are called global variables.

Declaring and naming global variables

By convention, global variables are declared at the top of a file, below the includes, but above any code. Here’s an example of a global variable being defined:

The above example prints:

3
3
5

By convention, many developers prefix global variable identifiers with “g” or “g_” to indicate that they are global.

Best practice

Consider using a g” or “g_” prefix for global variables to help differentiate them from local variables.

Global variables have file scope and static duration

Global variables have file scope (also informally called global scope or global namespace scope), which means they are visible from the point of declaration until the end of the file in which they are declared. Once declared, a global variable can be used anywhere in the file from that point onward! In the above example, global variable g_x is used in both functions doSomething() and main().

Because they are defined outside of a function, global variables are considered to be part of the global namespace (hence the term “global namespace scope”).

Global variables are created when the program starts, and destroyed when it ends. This is called static duration. Variables with static duration are sometimes called static variables.

Unlike local variables, which are uninitialized by default, static variables are zero-initialized by default.

Global variable initialization

Non-constant global variables can be optionally initialized:

Constant global variables

Just like local variables, global variables can be constant. As with all constants, constant global variables must be initialized.

A word of caution about (non-constant) global variables

New programmers are often tempted to use lots of global variables, because they can be used without having to explicitly pass them to every function that needs them. However, use of non-constant global variables should generally be avoided altogether! We’ll discuss why in a couple of lessons.

Quick Summary


6.5 -- Variable shadowing (name hiding)
Index
6.3 -- Local variables

264 comments to 6.4 — Introduction to global variables

  • Victor

    In lesson 6.6 — Internal linkage, it is said that "non-constant globals have external linkage by default" while in this lesson it is said "global variables have file scope (also informally called global scope or global namespace scope), which means they are visible from the point of declaration until the end of the file in which they are declared".

    Since, "an identifier with external linkage can be seen and used both from the file in which it is defined, and from other code files (via a forward declaration)", I didn't understand if global variables are actually global or file based.

    • nascardriver

      Scope and linkage are different.
      Scope is where you can _see_ the variable. A global variable can be seen from its declaration to the end of the file.
      Linkage is where you can access the variable (Independent of the scope). Although file A cannot see a global variable defined in file B, it can access the variable by using a forward declaration, because the variable has global linkage (It's globally accessible).

  • Jimmy Hunter

    I am loving this tutorial.  Just a small editing note here to help you make it better.
    In the first sentence of the Constant Global variables section, you have a typo.
    You typed "... can be be constant."
    I think you meant "... can be constant."

  • kavin

    In "introduction-to-global-variables"  Unlike local const/constexpr variables where const need not be initialized but constexpr need to be initialized, could you explain when we should use global const and global constexpr since both need to be initialized ?

    • Alex

      Constant variables (whether const or constexpr) must be initialized, otherwise there is no way to give them a value.

      You should favor constexpr whenever possible.

  • koe

    The beginning paragraphs are confusing, since it seems the words 'declaration' and 'definition' are used too loosely.

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

    This seems problematic since in section 2.7 we learn that a definition instantiates a variable. I would think this makes more sense (even this may not be correct since it uses the word 'refer', which may conflict with proper meaning of 'reference' in C++):

    "A variable's linkage determines whether appearances of its identifier in other files refers to it."

    Also, this note should be moved higher, since it's confusing from the beginning of this section which declarations are definitions and which are pure declarations.

    "Note that if you want to define an uninitialized non-const global variable, do not use the extern keyword, otherwise C++ will think you’re trying to make a forward declaration for the variable."

    My understanding is that global variables with no const, constexpr, or intern or extern, are extern (default). If it is intended to be an uninitialized definition, then it must be a declaration of the variable that does not have 'extern', and all other declarations of it must have 'extern'. Is this a rule or recommendation?

    Since const/constexpr must be initialized, the definition/declaration distinctions between intern and extern linkages are more clear.

    Also, here the word 'declared' seems improper, since forward declarations only make sense for definitions.

    "Similarly, in order to use an external global variable that has been declared in another file, you must use a variable forward declaration."

    • koe

      Note: my compiler errors out with [-Werror, -Wextern-initializer] from

      Update: after getting through this section I think this is a better definition of linkage
      "A variable's linkage determines whether the linker will associate appearances of its identifier in other files to that variable."

    • nascardriver

      Old: "A variable’s linkage determines whether multiple instances of an identifier refer to the same variable or not."
      New: "A variable’s linkage determines whether or not the variable can be used in a file other than the one it is defined in."

      Old: "in order to use an external global variable that has been declared in another file"
      New: "in order to use an external global variable that has been defined in another file"

      > Also, this note should be moved higher
      I added comments to the globals up to that point, stating whether they are definitions or declarations.

      > Note: my compiler errors out with
      I noted this after the first example that uses `extern`.

      > My understanding is that global variables with no const, constexpr, or intern or extern, are extern (default)
      Correct (I'm assuming you meant `static` when you said intern).

      > If it is intended to be an uninitialized definition, then it must be a declaration of the variable that does not have 'extern'
      Every definition is a declaration.

      Saying that this is a declaration is correct, but very confusing. It's a definition (And therefor a declaration).

      > and all other declarations of it must have 'extern'.
      Correct. Without `extern`, they'd be definitions, violating the one-definition-rule.

      > Is this a rule or recommendation?
      That's just how it is, you can't do it otherwise.

      Thank you very much for your feedback, it will help future readers to understand the topic better. If there's anything else or you don't agree with one of my updates, please let me know!

      • koe

        > Saying that this is a declaration is correct, but very confusing. It's a definition (And therefor a declaration).

        You're right, I should have just said "For uninitialized variables that are externally linked by default, their definitions cannot have 'extern' since this is the only way to distinguish them from their forward declarations which must have 'extern'."

  • Charan

    How can we forward declare a constexpr variable in an external file? I think the chapter says we could not. However there is a provision to initialise a constexpr variable with external linkage ,in a file. What is the purpose of this i.e to initialise with external linkage?

    • Charan

      Also, the final summary mentioned that constexpr must be initialised. But isn't it against the philosophy of constexpr ,to be initialised(and stay constant) by the user.?

    • nascardriver

      `constexpr` variables cannot be forward declared. They have to be initialized at their declaration.
      `extern constexpr` doesn't have any benefits code-wise. The linker will expose the name of the variable, which makes it easily accessible to other programs and libraries. There's probably a niche case where this is useful.

      `constexpr` is used for compile-time constants. They can't be initialized with a user-provided value.

      • koe

        How would other programs and libraries use an 'extern constexpr' variable if it can't be forward declared? Why can you forward define an 'extern const' variable even when its definition is a compile-time constant, but not 'extern constexpr'?

        • nascardriver

          > How would other programs and libraries use an 'extern constexpr' variable if it can't be forward declared?
          `dlsym` on unix, `GetProcAddress` in Windows. The other program can't declare the variable `constexpr`, but they can get the value of our `constexpr` variable.

          > Why can you forward define an 'extern const' variable even when its definition is a compile-time constant, but not 'extern constexpr'?
          The value of a `const` doesn't matter, because it's allowed to be a run-time or compile-time value. `constexpr` has to be initialized with a compile-time value. `constexpr` variables can be used for computations at compile-time. I suppose allowing separation of declaration and definition would make the compiler's job more difficult.

  • mooseymouse

    hi i dont unerstand something how can the compiler differentiate between a forward declaration of an external variable in an other file from defining a local variable like what if i wanted to define an uninitialised external  variable in main you said it wouldn't link as the linker interprets it as a forward declaration for variable in another file.  i am confused by this thanks,

    • Alex

      A variable forward declaration and a local variable have different syntaxes.

      If you want an uninitialized external global variable, use "int g_x", which is external by default (not "extern int g_x", which will be treated as a forward declaration).

  • Chandler

    All of your examples on this page initialize the variables using parenthesis.

    I thought this was done with the curly braces: { }

    • nascardriver

      Some lessons still use direct- or copy-initialization, thanks for pointing this one out! I updated it to use brace-initialization instead.

  • Tushar

    https://www.youtube.com/watch?v=hDfDnsvEodQ

    This video explains this concept very clearly. Had a hard time understanding this so save yourself and go through this tutorial

  • Fan

    Is it true that the order of initialization of global variables is undefined, even inside a single file? For example, the code

    produces
    1 3
    as if j=0 first, then i is initialized with 0+1=1, and finally j is initialized with 1+2=3.
    But then the code

    produces
    3 2
    as if j is initialized with 2 first, and then i is initialized with 2+1=3.

    • There are several initialization steps for non-local variables. First, variables that are initialized by a constant expression (eg. a number) are initialized. The rest of the variables is zero-initialized. This happens before your program starts running. The values are stored in the binary.
      Then, when your program starts running, the other variables in the current file are initialized in-order (This might also happen before your program starts running, but that's just an optimization).

      Example 1:
      `j` is zero-initialized, because it isn't initialized by a constant expression.
      `i` is zero-initialized, same reason as `j`.
      Now your program starts.
      `i` is initialized (0 + 1)
      `j` is initialized (1 + 2)

      Example 2:
      `j` is initialized to 2, because 2 is a constant expression.
      Now your program starts
      `i` is initialized (2 + 1)

      This order is well-defined.

      To take it a little further

      Output: 1 12 9

      `k` is initialized to 9, because 9 is a constant expression.
      `i` and `j` are 0.
      Now the program starts.
      `i` is initialized (0 + 1)
      `j` is initialized (9 + 3)

      There are exceptions, but none you'd have to worry about just yet.

  • hellmet

    I have a bunch of questions, some stupid perhaps...
    1) Why is it that a const has the exception that it has only internal linkage even when it is declared at the file scope (i.e. outside main)? (The explanation on StackOverflow didn't make sense to me)
    2) How would constexpr change things with each of the declarations shown in the summary? From what I recall (and I hope I understood this well) const is for values that do not change at runtime, once initialized; constexpr need to be initialized by compile time, so the compiler is free to replace all occurrences of the variable with the value it holds. So, does this mean whenever and wherever I include the header with something defined as constexpr, the compiler will replace them with that variable's values?
    3) Clearly, static and extern are opposing concepts. Is there any way I can include my 'secret' variable only select files and not in any other? Say I have a case where I am keeping track of number of students in a file, and to calculate the average expenditure per student, I want to get the number of students. This is a case where the finance.cpp and students.cpp are different, but need access to a single 'secret' variable. From what I've read so far, accomplishing that with static doesn't seem possible.

    • 1)
      It's likely that you need a `const` variable in multiple files. If you need something in multiple files, you put it in a header. A constant never changes, so you initialize it at its declaration. If you initialize a variable with external linkage at its declaration in a header, you'll run into trouble, because it's defined multiple times. If the variable has internal linkage, you can include it multiple times, because the other files don't see it.

      2)

      `g_w` makes me wonder why it's legal, maybe someone else can help.

      `constexpr` tells the compiler that the variable/function can be evaluated at compile-time. What the compiler does with this information is up to it. It might replace the occurrences of the variable with its value, but it doesn't have to.
      `constexpr` variables can be used in combination with `constexpr` functions to make sure that your code _could_ be evaluated at compile-time.

      3)
      `class` and `friend` (Covered later) will help you with keeping your secret. C++20's modules might also help, the future will tell.

      • hellmet

        Okay 3 makes sense!
        But I'm still worried I don't fully understand 1, 2.

        I'm trying to rationalize the meanings of const, constexpr, extern, internal vs external linkage, static and connect the dots so that I better understand and reason with their usage.

        This is how I understood them, please correct me if I'm wrong.

        1) A variable of the form 'int p' declared at the file level has external scope by default. Its forward declared as 'extern int p' in a header file that can be included in files that require it. This assures that any file #include-ing the relevant header file has the same copy.

        2) const, static give a variable internal linkage by default and can be declared+initialized as extern and forward declared in a header file if they are to be used outside the file. Consequently, any files including the header file will get the 'same copy' instead of being assigned new memory each time.  

        3) The advantage (over C) of 'const' having internal linkage is that it allows for both possibilities, having a local copy (by default) or by using the global unique copy allowing for customization of code.

        4) All variables or functions declared as 'constexpr' has a single memory by default, so it's redundant to use extern on its declaration. They can just be used as is, as long they are defined+declared in a header file and included, as they can't be forward declared

        Have I got this right?

        Sidenote, how do I find all my comments? It would be nice to have the links so that I can refer back to them later

        • 1)
          Correct

          2)
          `static` and `extern` can't be mixed. `static` has internal linkage.

          3)
          "global unique" might be misleading. Every file that includes a header in which a `const` variable was declared gets a copy of the variable. All of the variables will have the same value, but they're distinct objects.
          This is not the case for `constexpr` variables. They're the same in every file.

          4)
          Right. `const` variables can also be made to have a single memory location by declaring them `inline`. All `constexpr` variables are `inline` by default, that's why they do this.

          > how do I find all my comments?
          There's no friendly interface. You can use the wordpress api and run the result through a json beautifier to get a somewhat readable overview ( https://jsonbeautifier.org/?url=https%3A%2F%2Fwww.learncpp.com%2Fwp-json%2Fwp%2Fv2%2Fcomments%3Fper_page%3D100%26search%3Dhellmet ) (click on the little arrows on the right the expand the comments).

          • hellmet

            Thank you very much! That makes so much stuff clear!
            I really appreciate your patience and dedication in maintaining this site!
            I'll comeback someday, after I get a job and express my gratitude!

            • Have you found a method for accessing your comments yet?

              • hellmet

                Just follow what nascardriver said,

                It's in a json format, so it's a bit clunky. But you can get the link there if you wish to go back to the comment.

                • Well I just asked that for fun. I don't know if that json thing works well.
                  I just wanted to showcase my script  (well my first web scraping script) and i thought well why not make something useful. the only downside is that it does'nt display code. :(.

                  • if you fortunately use this stupid program change 'end' at line 34 in the for loop to 'end+1'.

                  • hellmet

                    Hey that's actually pretty neat!

                    I think you're only looking at the latest comments, since the url to a page lands you only on the latest comments. You can iterate over the comments pages by looking at the page URL. The general version is 'page-url'+'/comment-page-i' where i is the counter.

                    And to get the code, if you look closely, all the code is under '<td class="crayon-code">...</td>' the syntax highlighting takes more tags. All you need to do is get all the .text items for all tags under '<td class="crayon-code">' and concatenate them. That should spit out the code too under comments.

                    About the end, yes I did :) you might wanna cap end to 'last + 1'. Never trust user's input ;)

                    If you're learning bs4 or python, this is okay. But a better approach is to utilize the public link that Nascardriver gave us above. That uses the internal database to spit out all the comments by a giver user in a nice JSON file. You can then parse this file to get your comments and links to said comments. That's much more efficient than scraping a site (and you'll be saving some energy!).

                    Also, I'd politely ask for alex's and nascardriver's permission before you scrape their website, as courtesy :).

                    • Oh Thanks. I just used bs4 for the first time. Maybe i need to use it someday. Btw Can you please connect with me on any social media platforms. :). Incase I need your help. I have my small stupid website attached to my name. It has my contact info.

                  • nascardriver

                    Hi!

                    When you request the HTML page, you'll get a lot of unnecessary information and you have to parse the website to get the information you need. Many websites (Including learncpp) offer an API, making automated access faster and cheaper.
                    Learncpp runs wordpress, see the comment api documentation here https://developer.wordpress.org/rest-api/reference/comments/
                    As already shown by hellmet, an example request looks like this
                    https://learncpp.com/wp-json/wp/v2/comments
                    or, if you want to search for a specific word (Username)
                    https://learncpp.com/wp-json/wp/v2/comments?search=piyush

                    You should be able to find all of your comments in a matter of seconds.

  • murat yilmaz

    In find this topic hard to understand.

    What is the difference between scope and linkage?

    What is the difference between global variables and external variables? (They have automatically the extern keyword)

    What is the difference between intern variables and global variables or functions with the keyword "static"?

    Why would you want to make variables only visible to that specific file by placing the static keyword?

    • potterman28wxcv

      > What is the difference between scope and linkage?

      The scope defines where you can use a given variable in the C++ code.

      Linkage is the process of linking several object (binary) files into one executable. In this process, each object file has a number of symbols that are defined - if you create a constant in your C++ code, your constant will have a symbol in the object file. However, if your constant is static, then that symbol will not be able to be used by the other object files - the "scope" of the symbol will be local to the object file corresponding to your C++ source file.

      I'm not sure how exactly does a symbol stay local to an object file. But the result is that the other object files won't be able to see your symbol. So if you use your constant (that was defined static) in another C++ source file, the corresponding object will use it as well, but when the linker tries to form one executable, it won't be able to link the symbol to its location.

      I don't know if it makes it more clear - you might want to re-read the chapter about the compilation process.

      > What is the difference between intern variables and global variables or functions with the keyword "static"?

      Global variables and functions (with or without the static keyword), will have a symbol attached to them by the compiler, in the object file. If you compile with the -S option (which stops at the assembly), and then read the generated assembly, you will see that your static identifiers have all been translated into a symbol (something that ends with a ':').

      On the other hand, intern variables won't have any symbol attached to them. And the compiler will decide whether the intern variable will reside in a processor register, or somewhere on the stack (in memory), or a combination of both. By the way, it is much more efficient to manipulate registers than it is to manipulate memory, so intern variables will always be more efficient than global variables.

      > Why would you want to make variables only visible to that specific file by placing the static keyword?

      It's a bit like a principle of encapsulation. You want to know where this or that variable is used. If there is no static keyword, then that variable could be used anywhere in your code - and if a bug happens related to that specific variable, then it will potentially be a lot harder for you to pinpoint where something went wrong.

      In the examples of these tutorials it's always easy because you never have more than 100 lines of code. On real life projects (even those that you do by yourself), your codebase can reach easily 1000+ lines of code, sometimes even 10000. Good luck trying to find what went wrong if you only use global variables - moreover if none of these global variables have the "static" keyword.

      Global variables have their uses - but you should avoid them whenever you can. Because it is much simpler to reason in terms of local variables that reside in 40-50 lines of code, rather than having to deal with variables shared by all the program, and that could be modified anywhere.

      I'm not sure about the 2nd question.

    • Alex

      > What is the difference between global variables and external variables? (They have automatically the extern keyword)

      Nothing, they are the same thing.

  • Abhinav

    I have a question regarding linkage and duration with respect to your example above. Global variables have static duration right? So the variables inside constants.cpp are destroyed when we leave that program right? So how come if I #include constants.h in my main.cpp file, I can access constants defined in constants.cpp, even though constants.cpp has ended executing (Or its not?) ?

    edit: Is my following understanding correct:
          1)global variables (file scope) have static duration, i.e
          destroyed when file finishes execution.
          2)extern variables (true global scope) do not have static
          duration but persist even after file execution completes.

    • Files don't execute, files only matter to your compiler, but not a runtime. Static variables die when the program ends.

      > global variables (file scope) have static duration
      Yes

      > destroyed when file finishes execution
      No

      > extern variables (true global scope) do not have static duration
      They have static duration

      > persist even after file execution completes
      There is no "file execution", they die when the program ends.

  • Vir1oN

    Hey @Alex
    I’ve just read the chapter for several times, and one thing remains unclear: what happens with external variables’ scope, when they are exported to another file? You wrote:

    “Global variables have global scope (aka. file scope), which means they can be accessed from the point of declaration to the end of the file in which they are declared.”

    As well as:

    “Global variables have global scope, and can be used anywhere in the program“

    Thus I make the conclusion that scope must be renewed or something, or how the variable can be accessed in the other files otherwise?

    Also it’s still a bit hard for me to understand the difference between the terms of “linkage” and “scope”. In the quiz solution you wrote:

    “Scope determines where a variable is accessible”
    “Linkage determines whether the variable can be exported to another file or not”

    But couldn’t the second sentence be rephrased as “ linkage determines whether the variable can be accessed from another file or not”? If so, linkage seems to be scope in the broader sense. Or I just don’t understand it correctly?

    • Alex

      When a global variable is defined, in the file for which it is defined, it can then be accessed from the point of definition to the end of the file.
      However, via a forward declaration, the variable can be used from other files (assuming external linkage), from the point of the forward declaration to the end of the file containing the forward declaration. The compiler doesn't know this is the same variable as in another file.

      Scope works file by file and is enforced by the compiler.
      Linkage works across files, and is enforced by the linker.
      Thus, in order to be accessed from another file, the variable must have external linkage (to satisfy the linker) AND it must be in scope (to satisfy the compiler).

  • Sweta

    It was my understanding from one of the previous topics that constexpr must be used for constants that are initialised during compile-time, and const must be used for constants that are initialised during run-time, yet the above example uses "const" for compile-time initialisation. Is there a particular reason for this?

    • Alex

      Const can be used for either runtime or compile-time constants.

      It's more precise to use constexpr if you can, but it's not necessary to update older code/examples that already work unless there's a specific reason to.

  • Louis Cloete

    @Alex, since you suggest that one namespace non-const global variables, maybe you should explain how to forward declare a namespaced global variable. It has not been obvious to me when I wanted to use a global Mersenne twister over multiple files for the game in chapter 11.x's quiz. I found out by trial and error after a lot of different errors about duplicate definition and undefined symbols that it is like this:

    foo.cpp:

    bar.cpp:

    • Alex

      Thanks for the feedback. There's an example in this very lesson already on how to do this -- perhaps it wasn't obvious enough. I've updated the comments in the example to make it more explicit that the forward declarations need to go in a namespace.

  • Alireza

    Hi and greeting,
    I'm using Qt Creator 4.7.
    I have written this code:

    however in mathematical.cpp file:

    it gives me this warning for both variables @g_pi and g_gravity :

    What do you suggest for it ?

    • Include mathematical.h in mathematical.cpp so it sees the declaration, or use inline variables.

      By using inline variable you don't need another source file, because inline variables are allowed to be defined multiple times.

  • _weedfox

    So if im working with only 1 file is it better to use static since it will be only used for this file anyway or let it be external since its easier and wont be used external anyway?

Leave a Comment

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