Tentative definitions in C and linking

Solution 1:

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.

Solution 2:

There is something called a "common extension" to the standard, where defining variables multiple times is allowed as long as the variable is initialized only once. See http://c-faq.com/decl/decldef.html

The linked page says this is pertinent to Unix platforms--I guess it's the same for c99 as c89--though maybe it has been adopted by more compilers to form some sort of a defacto standard. Interesting.

Solution 3:

This is to clarify my answer to a comment by olovb:

output of nm for an object file compiled from "int x;". On this platform, symbols are prepended with a '_', that is, the variable x appears as _x.

00000000 T _main
         U _unknown
00000004 C _x
         U dyld_stub_binding_helper

output of nm for an object file compiled from "int x=1;"

00000000 T _main
         U _unknown
000000a0 D _x
         U dyld_stub_binding_helper

output of nm for an object file compiled from "int x=0;"

00000000 T _main
         U _unknown
000000a0 D _x
         U dyld_stub_binding_helper

output of nm for an object file compiled from "extern int x;"

00000000 T _main
         U _unknown
         U dyld_stub_binding_helper

EDIT: output of nm for an object file compiled from "extern int x;" where x is actually used in one of the functions

00000000 T _main
         U _unknown
         U _x
         U dyld_stub_binding_helper