I am very very sorry. I didn\'t know my incomplete code attachment would create such a mess. I am very glad to see so many sincere helps.
This code will compile:
extern int main_stat=-3;
declares and defines main_stat
, While:
extern int main_stat;
just declares the variable main_stat
.
You can have as many declarations as you want but you can have only one Definition.
The keyword extern
, indicates External Linkage. Without it main_stat
would be static and have Internal linkage and you cannot not use main_stat
from another translation unit.
Is storage allocated in the stack frame of myadd ?
No definitely not on the stackframe of add
.
Where the memory is allocated is implementation defined but you have the assurance that the object will be alive throughout the duration of the program.
First, according to your comment, the file containing the main function has the definition static int main_stat = 10;
. You should be aware that this is not
the same variable as you defined in the file containing myadd
because as static variable its scope is restricted to that file. Indeed, thanks to that static variable with the same name, main
is not able to access the variable you defined in this file.
But that doesn't mean that either variable was created on the stack. Both are separate global variables, it's just that the variable main_stat
in the file containing main
(I'll call that file main file for short, and this one myadd file) is not available in any other file, while the variable main_stat
you defined here can be accessed from any file which contains the declaration extern main_stat;
(note: without initializer!). The main file cannot contain this declaration, however, because it would conflict with the static variable of the same name.
Note that giving an initializer makes your declaration of the variable a definition, that is, it's the same as if you had omitted the extern (note however that if a variable is declared constant, the extern may not be omitted because constants are by default static). The only global extern declarations which are not also definitions are those with extern, but without initializer.
All variable declarations with an initializer are also definitions;
that's an overriding rule. Regardless of extern
. There are even
cases where you need an extern
on a definition: you can only
instantiate a template using a variable which has external linkage. And
const
variables have internal linkage by default, so you need
something like:
extern int const i = 42;
if you want to use it to instantiate a template<int const*>
.
The following is a declaration and definition:
int x;
Adding extern
says "make it a declaration only, please".
But when you are providing a value, the line has to be a definition, so the variable gets extern
storage class and you just happen to be defining it right in place anyway:
extern int x = 3;
The linkage semantics are as they usually are for extern
, and the storage location is just as it would be for a normal definition int x = 3
— i.e. in that TU at namespace scope. myadd
is not relevant at all.
It's a hard one to "prove", because it's a case of "there's no rule against it".
Here's the best quote:
[n3290: 3.1/2]:
A declaration is a definition unless it declares a function without specifying the function’s body (8.4), it contains theextern
specifier (7.1.1) or a linkage-specification25 (7.5) and neither an initializer nor a function-body, [..]
And some other pertinent information:
[n3290: 3.5/2]:
A name is said to have linkage when it might denote the same object, reference, function, type, template, namespace or value as a name introduced by a declaration in another scope:
- When a name has external linkage, the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.
- When a name has internal linkage, the entity it denotes can be referred to by names from other scopes in the same translation unit.
- When a name has no linkage, the entity it denotes cannot be referred to by names from other scopes.
[n3290: 3.5/12]:
The name of a function declared in block scope and the name of a variable declared by a block scopeextern
declaration have linkage. If there is a visible declaration of an entity with linkage having the same name and type, ignoring entities declared outside the innermost enclosing namespace scope, the block scope declaration declares that same entity and receives the linkage of the previous declaration. If there is more than one such matching entity, the program is ill-formed. Otherwise, if no matching entity is found, the block scope entity receives external linkage. [..]
Everyone else has covered this pretty well, but just to show the variants in one place:
int x; // #1
is a declaration and definition. The initial value of x
is zero.
int x = 3; // #2
is a declaration and definition.
const int cx; // #3
is illegal in C++.
const int cx = 3; // #4
is a declaration and definition, but cx
has internal linkage if this is its first declaration in the translation unit.
extern int x; // #5
is a declaration but NOT a definition. There must be a definition of x
somewhere else in the program.
extern int x = 3; // #6
is a declaration and a definition. The extern
is unnecessary, but makes things clear.
extern const int cx; // #7
is a declaration but NOT a definition. There must be a definition of cx
somewhere else in the program.
extern const int cx = 3; // #8
is a declaration and a definition. The extern
is needed unless the previous declaration above was already seen.
The question apparently stems from some misconception.
Some people believe that extern
keyword always turns a definition into a non-defining declaration. This is simply not true.
The keyword extern
simply gives the declared entity external linkage. It can be applied to declarations. It can be applied to definitions (and remember that definitions are declarations as well).
So, saying that one can't define an extern
entity is absolutely incorrect. One can. There's no problem with that at all.
The confusion is usually caused by the fact that when you apply extern
to a definition like
int x; // no initializer
that definition suddenly turns into a non-defining declaration. This is true, but this is is no more than a one-off quirk of extern
keyword that has to be remembered. If you take a definition like
int x = 42;
then applying the extern
keyword to it will still preserve it as a definition, i.e. no quirks in this case.