Why the following doesn't compile?
...
extern int i;
static int i;
...
but if you reverse the order, it compiles fine.
...
static int i;
extern int i;
...
What is going on here?
Why the following doesn't compile?
...
extern int i;
static int i;
...
but if you reverse the order, it compiles fine.
...
static int i;
extern int i;
...
What is going on here?
C++:
7.1.1 Storage class specifiers [dcl.stc]
So, the first one attempts to first gives
i
external linkage, and internal afterwards.The second one gives it internal linkage first, and the second line doesn't attempt to give it external linkage because it was previously declared as internal.
For C, quoting the standard, in C11 6.2.2: Linkage of identifiers:
(emphasis-mine)
That explains the second example (
i
will have internal linkage). As for the first one, I'm pretty sure it's undefined behavior:...because
extern
appears before the identifier is declared with internal linkage, 6.2.2/4 does not apply. As such,i
has both internal and external linkage, so it's UB.If the compiler issues a diagnostic, well lucky you I guess. It could compile both without errors and still be compliant to the standard.
In Microsoft Visual Studio, both versions compile just fine. On Gnu C++ you get an error.
I'm not sure which compiler is "correct". Either way, having both lines doesn't make much sense.
extern int i
means that the integeri
is defined in some other module (object file or library). This is a declaration. The compiler will not allocate storage thei
in this object, but it will recognize the variable when you are using it somewhere else in the program.int i
tells the compiler to allocate storage fori
. This is a definition. If other C++ (or C) files haveint i
, the linker will complain, that int i is defined twice.static int i
is similar to the above, with the extra functionality thati
is local. It cannot be accessed from other module, even if they declareextern int i
. People are using the keyword static (in this context) to keep i localize.Hence having
i
both declared as being defined somewhere else, AND defined as static within the module seems like an error. Visual Studio is silent about it, and g++ is silent only in a specific order, but either way you just shouldn't have both lines in the same source code.This is specifically given as an example in the C++ standard when it's discussing the intricacies of declaring external or internal linkage. It's in section 7.1.1.7, which has this exert:
Section 3.5.6 discusses how
extern
should behave in this case.What's happening is this:
static int i
(in this case) is a definition, where thestatic
indicates thati
has internal linkage. Whenextern
occurs after thestatic
the compiler sees that the symbol already exists and accepts that it already has internal linkage and carries on. Which is why your second example compiles.The
extern
on the other hand is a declaration, it implicitly states that the symbol has external linkage but doesn't actually create anything. Since there's noi
in your first example the compiler registersi
as having external linkage but when it gets to yourstatic
it finds the incompatible statement that it has internal linkage and gives an error.In other words it's because declarations are 'softer' than definitions. For example, you could declare the same thing multiple times without error, but you can only define it once.
Whether this is the same in C, I do not know (but netcoder's answer below informs us that the C standard contains the same requirement).