Tentative definitions in C and linking

See also What are extern variables in C. This is mentioned in the C standard in informative Annex J as a common extension:

J.5.11 Multiple external definitions

There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).

Warning

As @litb points out here, and as stated in my answer to the cross-referenced question, using multiple definitions for a global variable leads to undefined behaviour, which is the standard’s way of saying “anything could happen”. One of the things that can happen is that the program behaves as you expect; and J.5.11 says, approximately, “you might be lucky more often than you deserve”. But a program that relies on multiple definitions of an extern variable – with or without the explicit extern keyword – is not a strictly conforming program and not guaranteed to work everywhere. Equivalently: it contains a bug which may or may not show itself.

See also How do I use extern to share variables between source files?

As noted by Sven in a comment, and in my answer to “How do I use extern…”, GCC changed its default rules relatively recently. In GCC 10.x (from May 2020) and later versions, the default compilation mode uses -fno-common whereas in prior versions the default mode used -fcommon. The new behaviour means that you do not get away with multiple tentative definitions, which is what the C standard requires for strict conformance.

If you use GCC and have code that (ab)uses multiple tentative definitions, you can add -fcommon to the compilation process and it will work as before. However, your code is not maximally portable, and it would be better for the long-term to revise the code so that each variable is properly defined in one source file (that is linked with all programs that need to use that variable) and properly declared in one header that the source files which use the variable can all include (and the source file defining the variable should also include the header to ensure consistency).

Leave a Comment