Sorry guys I know my english is bad, but i made examples so that my question is more clearer.
a.cpp
#include <iostream>
using namespace std;
void funcfoo(){
cout << "test only" << endl;
}
int varfoo = 10;
b.cpp
#include <iostream>
using namespace std;
extern void funcfoo();
extern int varfoo;
int main(){
funcfoo();
cout << varfoo;
return 0;
}
Then I compile it like this "cl b.cpp a.cpp"
My question is. How come when I remove the "extern keyword before void funcfoo()" it works fine, but when i remove the extern keyword
before int var foo I get an error?
The issue is what each one of the lines of code means. int varfoo is a definition of a variable, while void funcfoo() is only a declaration. You can provide multiple declarations of an entity, but only one definition. The syntax to provide a declaration and only a declaration of a variable is by adding the extern keyword: extern int varfoo; is a declaration
3.1 [basic.def]/2 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 [...]
When you remove the extern from extern void funcfoo(); you are forward declaring it so you're code below will know what funcfoo() is. If you were to do that to a variable, you would actually be instantiating it and would conflict with your other file. Hence the extern is saying "it exists, trust me ;)" that it gets resolved from your other file.
Another way to think about it is that when you do int varfoo memory is allocated to hold the variable so it is both a definition and a declaration, when you do int foo() the function is declared but not defined so in a way the memory is not allocated. For functions the linkage is external by default so removing it doesn't matter but for the variable, if you say extern int varfoo the compiler will not allocate memory for it --it will assume that the variable is defined somewhere else.
I know this might be late, but I hope this helps in some way. Check the link below and it ll give an idea of what extern is and how it works.
http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/
Thank you
Related
head.h
#pragma once
namespace foo
{
int bar;
int funct1();
}
head.cpp
#include "head.h"
int foo::funct1()
{
return bar;
}
main.cpp
#include <iostream>
#include "head.h"
int main()
{
foo::bar = 1;
std::cout << foo::funct1() << std::endl;
return 0;
}
Error LNK2005 "int foo::bar" (?bar#foo##3HA) already defined in head.obj
I don't understand what is going on. I tried looking for the answer but everyone's questions are so specific to their code and don't even look close to the problem that I am having.
I am not including .cpp files into main. I am not redefining anything. I am literally just assigning 1 to the variable then returning it with a function in the same namespace. How is it being defined multiple times?
The header head.h is included in two compilation units head.cpp and main.cpp. So the variable bar is defined twice. You could declare the variable without its definition the following way
#pragma once
namespace foo
{
extern int bar;
int funct1();
}
and then define it in some cpp module.
This foo namespace-level bar declaration:
namespace foo
{
int bar;
}
is actually a definition.
To make it a declaration, mark the bar as extern in head.h:
namespace foo
{
extern int bar;
}
Then define it in head.cpp:
int foo::bar = 0;
head.h is included in both main.cpp and head.cpp.
So the variable is defined twice.
Possible Solution: make it inline. The "extern" solutions are also good, although older in approach.
namespace foo
{
inline int bar;
}
How is it being defined multiple times?
It is defined once in head.cpp and once in main.cpp. That is a total of two times. This violates the one definition rule, which states that there may only be one definition for every variable.
int bar;
This is a definition of a variable. You've included it into two translation units.
A variable can be declared without definition in an extern declaration:
extern int bar;
Replace the definition with such declaration, and put the definition into exactly one translation unit.
I am not redefining anything. I am literally just assigning 1 to the variable
You're redefining the variable!
head.cpp has one via #include "head.h", and main.cpp has one via #include "head.h".
You need to merely declare it (unusual but not too strange) in the header:
extern int bar;
…then define it in one translation unit. This is just like what you do with static class members (albeit with slightly different syntax).
Since C++17, you may do this by instead plopping the inline keyword on to your definition.
Alternatively, avoid mutable globals…
Do carefully note that foo is not a class, but a namespace. When you declare a free variable in the header file:
int bar;
And then #include this header file multiple times (into different CPP files, causing multiple translation unit compilations), you'd get a linker error. Everyone knows it.
And, you'd add extern attribute at the declaration, and define the variable elsewhere in one of the CPP/C file.
Putting a global variable into a namespace is nothing but giving the global variable a different name. Think if foo::bar as foo__NS__bar, and hence you must add extern in the header and define foo::bar at some locatoin.
Note that this is different from a non-static member variable of a class. A class variable doesn't need to be defined/declared this way since the class is a type. Each instantiated variable of class-type would have a separate copy of the variable.
Further to that, when you add a static variable in the class, you are giving that logically global variable another name. Thence, you must have that static-variable defined one of the CPP file.
If I have in header file
namespace Bob
{
extern const T x;
};
And in source file
extern const T Bob::x = 123;
Is the second extern in the source file required or optional?
I've searched and found conflicting information.
From this webpage:
http://msdn.microsoft.com/en-us/library/357syhfh.aspx
But to get the same behavior in C++, you must declare your const variable [in source file] as:
extern const int i = 2;
Usually, the extern keyword tells the compiler not to define a symbol, because it will be defined somewhere else. So writing e.g.
namespace Bob {
extern T x;
}
does not define the variable x, but rather declares it. You can have as many extern declarations as you like. However, if you do not provide a definition the linking will fail. So you have to define
T Bob::x;
somewhere in the code in order to provide the definition.
The const keyword is a little special here, because it implies internal linkage. This means, that the definition of x will not be visible outside the specific compilation unit where it was defined. To alter this behavior you do need to write
extern const T Bob::x = 123;
if you want x to be const and also reference it from other compilation units.
----yet another edit----
Just to be absolutely clear:
If a const variable is supposed to be referenced outside of its compilation unit, then you must explicitly declare it extern.
However, if the declaration is given separately from the definition, then the definition does not necessarily need to specify the keyword extern again. Yet another example for demonstration:
myheader.h
extern const int i;
This declares i a const integer with external linkage, but does not define it.
main.cpp, version 1
#include "myheader.h" //Through the include, the above declaration of `i` comes before its definition.
const int i=123; // Although the `extern` modifier is omitted here,
// it's still in effect because we already declared `i` as `extern`
// Therefore it makes no difference here, whether or not you specify `extern` again.
// The compiler knows this is a definition either way, because of the initialization.
main.cpp, version 2
//#include "myheader.h"
extern const int i=123; // this line is declaration and definition in one, because we did not include
// the declaration from myheader.h. Thus, to tell the compiler that you want
// `i` with external linkage, you MUST specify `extern`. Otherwise you'll get
// internal linkage.
I hope all this now makes sense to you.
You can control the linkage of a symbol with the static and extern keywords. The default linkage is extern for non-const symbols and static (i.e. internal) for const symbols at namespace scope. This is valid for C++ but not for C (where you would have to declare it as static to make it have internal linkage).
So if you have
const int i = 2;
into a .c file and you use it into another unit by declaring
extern const int i;
that's fine in C since that variable has external linkage by default (and with the extern keyword you're instructing the compiler to find it into another unit), but in C++ the same
const int i = 2;
into a .cpp file (firmstanding what I wrote) has internal linkage and it would have to be defined with
extern const int i = 2;
to explicitly have external linkage and be able to be used into another unit with
extern const int i;
Finally when you initialize a global variable you're always defining it in the module where you're doing it, this means that the following is perfectly valid:
#include <iostream>
using namespace std;
#define T int
extern const T x; // This is a declaration
extern const T x = 123; // This is a definition
int main() {
std::cout << x; // 123
return 0;
}
That means the second 'extern' keyword is also unnecessary.
extern is a storage class in C. How exactly does it work? The output of the code given below is 20. How is this the output?
#include <stdio.h>
int main()
{
extern int a;
printf("%d", a);
return 0;
}
int a=20;
It means three things:
The variable has external linkage, and is accessible from anywhere in the program;
It has static storage duration, so its lifetime is that of the program (more or less); and
The declaration is just a declaration, not a definition. The variable must also be defined somewhere (either without the extern, or with an initialiser, or in your case, both).
Specifically, your extern int a; declares that the variable exists, but doesn't define it at that point. At this point, you can use it, and the linker will make sure your use refers to the definition. Then you have the required definition, int a=20; at the end, so all is well.
extern in this case indicates that the symbol a is defined in a different location, such as a different module. So the linker looks for a symbol with the same name in all of the modules that are linked, and if one exists then it sets the address to your local variable a with the address to the externally defined variable. Since you have another a defined outside of your main() function, the a inside your main() function is (basically) the same variable as the one outside.
Since the global a is initialized before the main function executes, the value is 20 by the time you access it.
extern means i declare a variable, just like you implement a function in a source file and declare the prototype in a header to allow other source file to use it.
If you put a global variable in a source file, and use a header to declare it with the extern keyword, each source file including the header will see the variable.
The linker will do the job to tie everything just as it does with functions
extern as a storage class specifier tells the compiler that the object being declared is not a new object, but has storage elsewhere, i.e., is defined elsewhere. You can try this experiment with your code to see how it works. Leave out the keyword extern in your declaration of int a in main(). Then your printf() will print some garbage value, as it would be a new definition of an int with the same identifier, which would hide the global a declared elsewhere.
You use extern to tell the compiler that the variable is defined elsewhere. Without extern in your program compiler would define another variable a (in addition to this in the global scope) in your main() function that would be printed uninitialized.
I know one should not use global variables but I have a need for them. I have read that any variable declared outside a function is a global variable. I have done so, but in another *.cpp file, that variable could not be found. So it was not really global. Isn't it so that one has to create a header file GlobalVariabels.h and include that file to any other *cpp file that uses it?
I have read that any variable declared outside a function is a global variable. I have done so, but in another *.cpp File that variable could not be found. So it was not realy global.
According to the concept of scope, your variable is global. However, what you've read/understood is overly-simplified.
Possibility 1
Perhaps you forgot to declare the variable in the other translation unit (TU). Here's an example:
a.cpp
int x = 5; // declaration and definition of my global variable
b.cpp
// I want to use `x` here, too.
// But I need b.cpp to know that it exists, first:
extern int x; // declaration (not definition)
void foo() {
cout << x; // OK
}
Typically you'd place extern int x; in a header file that gets included into b.cpp, and also into any other TU that ends up needing to use x.
Possibility 2
Additionally, it's possible that the variable has internal linkage, meaning that it's not exposed across translation units. This will be the case by default if the variable is marked const ([C++11: 3.5/3]):
a.cpp
const int x = 5; // file-`static` by default, because `const`
b.cpp
extern const int x; // says there's a `x` that we can use somewhere...
void foo() {
cout << x; // ... but actually there isn't. So, linker error.
}
You could fix this by applying extern to the definition, too:
a.cpp
extern const int x = 5;
This whole malarky is roughly equivalent to the mess you go through making functions visible/usable across TU boundaries, but with some differences in how you go about it.
You declare the variable as extern in a common header:
//globals.h
extern int x;
And define it in an implementation file.
//globals.cpp
int x = 1337;
You can then include the header everywhere you need access to it.
I suggest you also wrap the variable inside a namespace.
In addition to other answers here, if the value is an integral constant, a public enum in a class or struct will work. A variable - constant or otherwise - at the root of a namespace is another option, or a static public member of a class or struct is a third option.
MyClass::eSomeConst (enum)
MyNamespace::nSomeValue
MyStruct::nSomeValue (static)
Declare extern int x; in file.h.
And define int x; only in one cpp file.cpp.
Not sure if this is correct in any sense but this seems to work for me.
someHeader.h
inline int someVar;
I don't have linking/multiple definition issues and it "just works"... ;- )
It's quite handy for "quick" tests... Try to avoid global vars tho, because every says so... ;- )
This is from the <iostream>:
namespace std
{
extern istream cin; ///< Linked to standard input
extern ostream cout;
...
It seems by using extern the data types defined in other namespaces will just be available?
extern means "these variables are defined in some other compilation unit (.cpp or .lib file)"
In this case, you #include <iostream> into your .cpp file, and because cin and cout are declared as extern, the compiler will let you use them without complaining. Then, when the linker runs, it looks up all of the extern variables and sorts it all out.
extern is used to refer to a variable defined in a different compilation unit (for now, you can think of a compilation unit as a .cpp file). The statements in your example declare rather than define cin and cout. It is telling the compiler that the definition of these objects is found in another compilation unit (where they are not declared as extern).
No, this is an explicit way to say cin and cout are declared without actually defining them.
The extern keyword tells the compiler that a variable is declared in another source(i.e outside the current scope). The linker then finds this actual declaration and sets up the extern variable to point to the correct location.
variables declared by extern statements will not have any space allocated for them, as they should be properly defined elsewhere. If a variable is declared extern, and the linker finds no actual declaration of it, it will show error.
Eg. extern int i;
//this declares that there is a variable named i of type int, defined somewhere in the program.
Some answers say here that extern means that variable is defined in other compilation unit. Then, following should not compile as no other compilation unit or file is provided to compiler.
extern int a;
int main(){
std::cout<<a<<std::endl; //Prints 3
}
int a=3;
So, I think extern is explicitly used to separate the declaration and definition in case of variable as stated in one of answer. I think it is useless in case of functions.