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.
External variables are also known as global variables. These variables are defined outside the function. These variables are available globally throughout the function execution. The value of global variables can be modified by the functions. “extern” keyword is used to declare and define the external variables.
Global variable is a variable that is available throughout the program. An extern variable is also available throughout the program but extern only declares the variable but it doesn't allocate any memory for this variable. It means you can't ise the variable till you define it.
In a const variable declaration, it specifies that the variable has external linkage. The extern must be applied to all declarations in all files. (Global const variables have internal linkage by default.)
Best way to declare and define global variables The clean, reliable way to declare and define global variables is to use a header file to contain an extern declaration of the variable. The header is included by the one source file that defines the variable and by all the source files that reference the variable.
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 atypedef
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With