The keyword extern

Location
  1. Courses

    /

  2. Complete C++ Course

    /

  3. The basics

    /

  4. The keyword extern

Declaring variables

We saw how to declare functions and how to define them. We have also seen how to define variables, but no how to declare them.

Let us look at the following example:

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream> int main() { std::cout << VAR << std::endl; // Error: the variable VAR does not exist. return 0; } const int VAR=5;

In the example above, the variable VAR can not be used in the main function, because it is defined after it. The reason it that when the compiler is compiling the main function, it is not aware the variable VAR exists.

We can resolve that problem by either defining or declaring the variable before the main function. A variable is declared by writing the keyword extern, then the variable type and then the name of the variable followed by a semicolon ;.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream> extern const int VAR; int main() { std::cout << VAR << std::endl; /* It works. */ return 0; } const int VAR=5;

Note that as long as the variable is declared, the variable definition can be located in an other file. Usually, global variables are declared in header files and defined in source files (Like functions).

Static function

Let us look at the files of code below:

function1.hpp

1
2
3
4
5
6
#ifndef FUNCTION1_HPP #define FUNCTION1_HPP void function1(); #endif

function2.hpp

1
2
3
4
5
6
#ifndef FUNCTION2_HPP #define FUNCTION2_HPP void function2(); #endif

function1.cpp

1
2
3
4
5
6
7
8
9
10
#include "function1.hpp" void function3() { } void function1() { function3(); }

function2.cpp

1
2
3
4
5
6
7
8
9
10
#include "function2.hpp" void function3() { } void function2() { function3(); }

main.cpp

1
2
3
4
5
6
7
8
9
10
#include "function1.hpp" #include "function2.hpp" int main() { function1(); function2(); return 0; }

Yeah, the example above does absolutely nothing. Trying to compile that example would however cause an error because the function function3 is defined 2 times. Actually, the compiler would not complain and would generate the object files. The file function1.cpp is not included in function2.cpp and the other way around too, so only one definition of function3 exists in each file. So, why is there an error? The error happens when the linker tries to link the object files. Since the memory addresses of the functions are unknown to the compiler (the executable file is not yet assembled) it can not write the address of the functions when it outputs the instruction to call them. For that reason, it simply writes the name of the functions instead of their addresses and gives the job to the linker to replace them by their locations when the function addresses will be known. You see the problem? The linker assembles the object files together to produce the executable file. Then, when it tries to replace the name of the functions by their addresses, it realizes that there are 2 definitions of the function function3 in the executable file, so it does not know which function address (The address of the definition) to use.

The reason is that, by default, functions are defined as extern, which has the effect of allowing them to be used from other files, as long as they are declared in them.

The two following function definitions are equivalent:

void function() { } extern void function() { }

When a function is defined with the keyword static, its linking is done only inside the file it is defined in (Can only be used within that file). That therefore resolves the problem we had in the example above.

function1.cpp

1
2
3
4
5
6
7
8
9
10
#include "function1.hpp" static void function3() { } void function1() { function3(); }

function2.cpp

1
2
3
4
5
6
7
8
9
10
#include "function2.hpp" static void function3() { } void function2() { function3(); }

Defining the two functions named function3 with the keyword static makes the example above link without any error.