Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

twisted logic: a global variable in one file refers to an extern variable but is also referred by that extern variable

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.

like image 524
henryyao Avatar asked Jun 12 '15 12:06

henryyao


People also ask

What is a global extern variable?

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.

What is the difference between global and extern variable?

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.

Are global variables extern by default?

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.)

How do you declare a global variable in C extern?

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.


1 Answers

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.

like image 155
Lightness Races in Orbit Avatar answered Oct 27 '22 01:10

Lightness Races in Orbit