Why your code won't compile: the mystery of extern in C++
\n\nHave you ever written a neat C++ program, split it into several files, compiled it — and got a wall of errors like multiple definition of 'myVariable' or undefined reference to 'myVariable'? Sound familiar? If so — you are not alone. The question "How do I use extern to share variables between source files?" is among the top most popular on Stack Overflow with tens of thousands of views.
The problem is simple: when a project grows, keeping all the code in one main.cpp is impossible. But how do you make a variable declared in config.cpp visible in game.cpp and render.cpp? Intuition says: "Just declare it globally!" — but the compiler thinks otherwise. A small but mighty keyword extern comes to the rescue. Let's figure out how it works in practice so you never get confused about linking again.
What is extern and why is it needed?
\n\nIn C++, every name (variable, function, class) must be declared before use and defined exactly once. A definition is what allocates memory. A declaration is just a promise to the compiler: "Don't worry, the definition exists somewhere in another file, I'll show you the type and name."
\n\nThe extern keyword is exactly such a promise. It tells the compiler: "This variable is defined elsewhere, don't allocate memory for it here — just give me access to it".
Without extern, every attempt to declare a global variable in two .cpp files will lead to a linker error: two definitions — two memory locations — conflict.
The three-file rule: how to organize code
\n\nThe standard pattern for sharing variables between files in C++ looks like this:
\n\n- \n
- Definition file (*.cpp) — contains one definition of the variable. \n
- Header file (*.h) — contains the
externdeclaration of the variable. \n - Any other .cpp file — includes the header and uses the variable. \n
Example 1: Sharing an integer
\n\nImagine we are writing a game and want to store a global score in a separate file. Here's how to do it correctly.
\n\nFile: globals.cpp — this is where the real variable lives:
// globals.cpp\n#include "globals.h"\n\nint gameScore = 0; // Definition: memory is allocated here\n\nFile: globals.h — declaration for everyone else:
// globals.h\n#ifndef GLOBALS_H\n#define GLOBALS_H\n\nextern int gameScore; // Declaration: "look for the definition in another .cpp"\n\n#endif // GLOBALS_H\n\nFile: main.cpp — we use the variable:
// main.cpp\n#include <iostream>\n#include "globals.h"\n\nvoid updateScore(int points) {\n gameScore += points; // Works! extern gave access\n}\n\nint main() {\n gameScore = 100;\n updateScore(50);\n std::cout << "Score: " << gameScore << std::endl; // Outputs 150\n return 0;\n}\n\nFile: display.cpp — another file that needs access:
// display.cpp\n#include <iostream>\n#include "globals.h"\n\nvoid showScore() {\n std::cout << "Current score: " << gameScore << std::endl;\n}\n\nNote: gameScore is defined exactly once — in globals.cpp. Everywhere else we use extern int gameScore (via the header).
Common mistake #1: defining in the header file
\n\nBeginners often write this in a .h file:
// BAD: ba