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.

Related content

We discuss global constants in more detail in lesson %Failed lesson reference, id 9391%.

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 upcoming lesson 6.9 -- Why (non-const) global variables are evil.

Quick Summary


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

45 comments to 6.4 — Introduction to global variables

  • joel.giedt

    I will give a concrete example of when global variables are necessary. This is not to imply that they should not be kept to a minimum --- that is certainly true.

    Suppose you are a lattice gauge theorist writing a library intended to solve for quark propagators on GPUs (example, QUDA). It is going to be used by hundreds of people who are integrating it with other codes that they are already using. You want to present users of your library with as simple an interface as possible. That would just be a small set of functions to call, with no fancy abstract types, and perhaps a structure or two to contain parameters. The basic user will be solving a linear algebra problem, MX=B, where M is a large sparse matrix, B is a given "source" vector, and X will be the solution vector. For practical reasons this is done in two steps:

    void load_gauge(void *gauge_array, Params *par);
    void solve(void *solution, void *source);

    load_gauge is done once, but solve is typically done many times with different sources. void pointers are used because different precisions of floating point number are in use, depending on a setting in par. That is for performance reasons. The array gauge_array is loaded to the GPU and a pointer (not gauge_array) to that memory on the GPU must be passed somehow to solve() so that its own functions that it calls to carry out the operation on the GPU can use this array for defining the matrix M. To keep the interface simple, and to hide all of these implementation details from users, the pointer to the GPU memory is passed between the functions using a global variable, say gpu_gauge_array. Note that it is not even in the same memory space as gauge_array.

    The alternative is to force users of the library to adapt to a much more involved interface where they would call functions that are members of classes so that the pointer could be a member variable. This is far from optimal since half the community is actually using C code, not C++ code. By using the simple function interface given above, and a struct for the Params type, it can interface with either type of user. Of course everything in the interface code has to be declared with extern "C", but that is not a big deal.

    The point of this example is that in the professional setting you may not be writing code just for yourself, or for one company, but you may be writing for a world-wide community that needs simple, flexible code to link to and use. Having a simple interface will often force some data into global scope.

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">