Step 3 of 7
extern and shared state
A global variable defined in one file can be used from other files. The file that uses it needs a declaration saying "this variable exists, with this type, defined somewhere else". That's what extern is for:
/* config.h: the declaration, included wherever it's used */
extern int max_rounds;
/* config.c: the one definition, which actually creates the variable */
int max_rounds = 30;
Declaration vs definition
This distinction runs through all of C:
- A declaration tells the compiler a name and its type. There can be many.
- A definition creates the thing (reserves memory for a variable, or provides a function's body). There must be exactly one.
For functions, a prototype is a declaration and is implicitly extern. For variables, extern int x; is a declaration, while int x = 5; at file scope is a definition.
#include <stdio.h>
extern const char *app_name;
extern int version;
int main(void) {
printf("%s v%d\n", app_name, version);
return 0;
}
const char *app_name = "arena";
int version = 3;
arena v3
Here the declarations come first, so main can use the variables that are defined further down. In a real project the definitions would be in another file.
A warning about globals
Mutable globals are convenient and dangerous. Any code anywhere can change them, so bugs are hard to trace; tests interfere with each other; and threads race on them. Large codebases prefer passing a struct (like a Config *) to the functions that need it. Globals are at their best when they're const.
Your turn: declare max_rounds with extern above main so it can be used before the definition that appears later in the file.
Previous: static functions and variables Next: const-correct interfaces