int foo;
at file scope is a declaration of a "common" symbol.
int foo = 1;
at file scope is a definition of a symbol (with external linkage).
extern int foo;
at file scope is a declaration of an external symbol.
In general, common symbols should be avoided.
As I understand it, if the linker finds common symbol references but no definition for it, it will make one with no warning.
By contrast, there must be exactly one definition to satisfy references to external symbols.
For greater clarity, I'll quote from the GNU ld
manual's explanation of its --warn-common
option:
--warn-common
Warn when a common symbol is combined with another common symbol or with a symbol definition. Unix linkers allow this somewhat sloppy
practice, but linkers on some other operating systems do not. This
option allows you to find potential problems from combining global
symbols. Unfortunately, some C libraries use this practice, so you may
get some warnings about symbols in the libraries as well as in your
programs.
There are three kinds of global symbols, illustrated here by C examples:
int i = 1;
A definition, which goes in the initialized data section of the output file.
extern int i;
An undefined reference, which does not allocate space. There must be either a definition or a common symbol for the variable
somewhere.
int i;
A common symbol. If there are only (one or more) common symbols for a variable, it goes in the uninitialized data area of the
output file. The linker merges multiple common symbols for the same
variable into a single symbol. If they are of different sizes, it
picks the largest size. The linker turns a common symbol into a
declaration, if there is a definition of the same variable.
The --warn-common
option can produce five kinds of warnings. Each warning consists of a pair of lines: the first describes the
symbol just encountered, and the second describes the previous symbol
encountered with the same name. One or both of the two symbols will be
a common symbol.
Turning a common symbol into a reference, because there is already a definition for the symbol.
file(section): warning: common of `symbol'
overridden by definition
file(section): warning: defined here
Turning a common symbol into a reference, because a later definition for the symbol is encountered. This is the same as the
previous case, except that the symbols are encountered in a different
order.
file(section): warning: definition of `symbol'
overriding common
file(section): warning: common is here
Merging a common symbol with a previous same-sized common symbol.
file(section): warning: multiple common
of `symbol'
file(section): warning: previous common is here
Merging a common symbol with a previous larger common symbol.
file(section): warning: common of `symbol'
overridden by larger common
file(section): warning: larger common is here
Merging a common symbol with a previous smaller common symbol. This is the same as the previous case, except that the symbols are
encountered in a different order.
file(section): warning: common of `symbol'
overriding smaller common
file(section): warning: smaller common is here