fileA.cpp:

#include <iostream>
extern int iA;
extern int iB= iA;
int main()
{
std::cout<<iA<<','<<iB;
}

fileB.cpp

extern int iB;
extern int iA = 2*iB;

Compiled and linked and ran, out come in the debug and release mode is 0,0 My question is how it works, why there is no issue in linking stage? I'm using VC++2003.

1

There are 1 answers

3
Lightness Races in Orbit On BEST ANSWER

The initialiser overrides the extern keyword, so there's nothing "magical" about this: you're just declaring and defining two completely unrelated variables in different translation units.

From Standard for Programming Language C++ - Chapter 3.1:

A declaration is a definition unless it declares a function without specifying the function’s body (8.4), it contains the extern specifier (7.1.1) or a linkage-specification25 (7.5) and neither an initializer nor a function-body, it declares a static data member in a class definition (9.2, 9.4), it is a class name declaration (9.1), it is an opaque-enum-declaration (7.2), it is a template-parameter (14.1), it is a parameter-declaration (8.3.5) in a function declarator that is not the declarator of a function-definition, or it is a typedef declaration (7.1.3), an alias-declaration (7.1.3), a using-declaration (7.3.3), a static_assert-declaration (Clause 7), an attribute-declaration (Clause 7), an empty-declaration (Clause 7), or a using-directive (7.3.4).

Your program is thus equivalent to the following:

fileA.cpp

#include <iostream>
extern int iA;
int iB= iA;
int main()
{
std::cout<<iA<<','<<iB;
}

fileB.cpp

extern int iB;
int iA = 2*iB;

Both objects necessarily undergo static initialization (to bitwise all-zeroes) before anything else happens. When dynamic-initialization later takes place, depending on whether the static-storage-duration objects in fileA.cpp or fileB.cpp get initialised first (and you can't know what order that'll be) either iB is initialized to a zero iA (then iA is initialized to 2*iB as expected), or iA is initialised to a zero iB multiplied by two, which is still zero (then iB is initialized to a zero iA).

Either way, both objects are going to end up, via well-defined semantics, having a value of zero.