...
#include "test1.h"
int main(..)
{
count << aaa <<endl;
}
aaa
is defined in test1.h
,and I didn't use extern keyword,but still can reference aaa
.
So I doubt is extern
really necessary?
...
#include "test1.h"
int main(..)
{
count << aaa <<endl;
}
aaa
is defined in test1.h
,and I didn't use extern keyword,but still can reference aaa
.
So I doubt is extern
really necessary?
If aaa is not defined in another compilation unit you don't need extern, otherwise you do.
If your test1.h has the definition of aaa and you wanted to include the header file into more than one translation unit you will run into multiple definition error, unless aaa is constant. Better you define the aaa in a cpp file and add extern definition in header file that could be added to other files as header.
Thumb rule for having variable and constant in header file
extern int a ;//Data declarations
const float pi = 3.141593 ;//Constant definitions
Since constant have internal linkage in c++ any constant that is defined in a translation unit will not be visible to other translation unit, but it is not the case for variable they have external linkage i.e., they are visible to other translation unit. Putting the definition of a variable in a header, that is shared in other translation unit would lead to multiple definition of a variable, leading to multiple definition error.
In that case, extern
is not necessary. Extern is needed when the symbol is declared in another compilation unit.
When you use the #include
preprocessing directive, the included file is copied out in place of the directive. In this case you don't need extern
because the compiler already know aaa
.
I've found the best way to organise your data is to follow two simple rules:
By declare, I mean notify the compiler that things exist, but don't allocate storage for them. This includes typedef
, struct
, extern
and so on.
By define, I generally mean "allocate space for", like int
and so on.
If you have a line like:
int aaa;
in a header file, every compilation unit (basically defined as an input stream to the compiler - the C file along with everything it brings in with #include
, recursively) will get its own copy. That's going to cause problems if you link two object files together that have the same symbol defined (except under certain limited circumstances like const
).
A better way to do this is to define that aaa
variable in one of your C files and then put:
extern int aaa;
in your header file.
Note that if your header file is only included in one C file, this isn't a problem. But, in that case, I probably wouldn't even have a header file. Header files are, in my opinion, only for sharing things between compilation units.
extern
has its uses. But it mainly involves "global variables" which are frowned upon. The main idea behind extern
is to declare things with external linkage. As such it's kind of the opposite of static
. But external linkage is in many cases the default linkage so you don't need extern
in those cases. Another use of extern
is: It can turn definitions into declarations. Examples:
extern int i; // Declaration of i with external linkage
// (only tells the compiler about the existence of i)
int i; // Definition of i with external linkage
// (actually reserves memory, should not be in a header file)
const int f = 3; // Definition of f with internal linkage (due to const)
// (This applies to C++ only, not C. In C f would have
// external linkage.) In C++ it's perfectly fine to put
// somethibng like this into a header file.
extern const int g; // Declaration of g with external linkage
// could be placed into a header file
extern const int g = 3; // Definition of g with external linkage
// Not supposed to be in a header file
static int t; // Definition of t with internal linkage.
// may appear anywhere. Every translation unit that
// has a line like this has its very own t object.
You see, it's rather complicated. There are two orthogonal concepts: Linkage (external vs internal) and the matter of declaration vs definition. The extern
keyword can affect both. With respect to linkage it's the opposite of static
. But the meaning of static
is also overloaded and -- depending on the context -- does or does not control linkage. The other thing it does is to control the life-time of objects ("static life-time"). But at global scope all variables already have a static life-time and some people thought it would be a good idea to recycle the keyword for controlling linkage (this is me just guessing).
Linkage basically is a property of an object or function declared/defined at "namespace scope". If it has internal linkage, it won't be directly accessible by name from other translation units. If it has external linkage, there shall be only one definition across all translation units (with exceptions, see one-definition-rule).