In my project, I have a header file containing the following lines.
extern enum class options {alpha, beta, gamma, theta};
extern options P1, P2;
Compilation gives me
error: a storage class can only be specified for objects and
functions
Why?
How can I rectify this?
Compiler: GCC 9.2.0
extern is applied to variables to specify that they have external linkage. What you have is not a variable but an enum definition, therefore extern cannot be applied to it.
What you can do is apply extern to variables at file scope of the enum type.
For example, your header file would have:
enum options {alpha, beta, gamma, theta};
extern options myoption;
And in one source file you would have:
options myoption;
There's no storage associated with an enum class definition. So it doesn't make sense for it to be marked as extern.
A variable whose type is an enum class, on the other hand, can certainly be extern because there's storage associated with a variable to hold the value of that variable. The location of this storage is something that the linker must ultimately work out.
It makes sense to know of the existence of a variable without being responsible for designating storage for it at link time. This is how you get global variables. For example:
main.cpp
int foo = 5; // declaration and definition together.
other.cpp
extern int foo; // declaration only, (external definition still required elsewhere)
// but you can now use `foo` in this file. e.g.:
int examineFoo() {
return foo;
}
This is also useful if you want to provide a declaration of a global variable in a header file. For example:
main.cpp
#include "foo.h"
int foo = 5;
foo.h
extern int foo;
other.cpp
#include "foo.h"
int examineFoo() {
return foo;
}
It's okay to encounter both the extern declaration and the definition in the same file. e.g.:
extern int foo;
int foo = 5;
To fix your problem
To fix exactly the example you provided, you can remove extern from the enum class definition, where it does not make sense to have it.
enum class options {alpha, beta, gamma, theta};
extern options P1, P2;
Remember that some non-extern definition of those variables P1 and P2 will be required in another module in order for your program to link if you make use of them.
For you, you probably want the class to be defined in a header, along with an extern declaration of any global variables (yuck) you want in your program.
options.h
enum class options {alpha, beta, gamma, theta};
extern options P1, P2;
options.cpp
#include "options.h"
options P1 = options::alpha, P2 = options::beta;
In options.cpp you include options.h to get the definition of the enum class. It also came with an extern definition of the global variables P1 and P2, which wasn't strictly necessary as they are going to be defined in this file anyway, but it's not illegal to do it.
other.cpp
#include "options.h"
options examineOptionP1() {
return P1;
}
other.cpp is aware of the class definition for options and is aware of extern declarations of P1 and P2.
Related
I wants to export a global variable from dll I define the global variable like below. Assume this variable is defined in A.cpp
extern "C" __declspec(dllexport) int A;
Meanwhile, within the dll, another source file B.cpp wants to use and modify this value. I am wonderring how to declare the variable within B.cpp before using it.
extern "C" int A; ?
If in this case, how does compile recognize between declare and definition?
extern extern "C" int A; ?
It's definitely ill-formed.
Per [basic.def]/2.2, a declaration of an object at namespace scope is a definition unless:
it contains the extern specifier (9.2.1) or a linkage-specification19 (9.11) and neither an initializer nor a function-body,
...
19 Appearing inside the brace-enclosed declaration-seq in a linkage-specification does not affect whether a declaration is a definition.
Thus:
extern "C" int A; is a declaration.
extern "C" int A = 0; is a definition.
The below defines A and B, and declares C: the effect is the same as it would be without the extern "C" block, except that the entities declared have C linkage instead of C++ linkage.
extern "C" {
int A;
extern int B = 0;
extern int C;
}
extern extern "C" int A; ?
extern "C" can be used as a block:
extern "C"
{
extern int A;
}
The declaration needs to be in a header file like A.h or other code files cannot use it. The dllexport is especially useless without a header file. You probably want some kind of DLLEXPORT macro so you can define it to dllexport and dllimport as necessary. See pretty much any Windows DLL code.
Then in a cpp file you include the header. That allows your code to use the variable which is declared extern.
In one of your cpp files you include the header AND then define the variable using the same type and name and no extern. The linker will then put the data storage for it into the same module as the rest of that cpp file and all other uses of the name get linked to that definition.
However, just like private member variables in C++ it is a bad idea to expose global variables in a DLL. It is much better to hide access to them behind function calls.
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.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is external linkage and internal linkage in C++
Actually I want to know the importance of extern.
First I wrote some code :
file1.h
extern int i;
file2.c
#include<stdio.h>
#include "file1.h"
int i=20;
int main()
{
printf("%d",i);
return 0;
}
Now my question is that: what is the use of extern variable when I have to define the i in file2.c, declaring in file1.h is in which way useful to me .
sudhanshu
extern allows you to declare a variable (notify the compiler of its existence) without defining it (bringing it into existence). The general rule is that you can declare things as many times as you want, but you can only define them once.
This is useful if, for example, it will be defined elsewhere.
Consider:
file1.c: file2.c:
extern int xyzzy; int xyzzy;
void fn (void) {
xyzzy = 42;
}
When you link together those two functions, there will be one xyzzy, the one defined in file2.c, and that's the one that fn will change.
Now that happens even without the extern. What the extern does is to declare that xyzzy exists to file1.c so that you don't get any I don't know what the blazes "xyzzy" is errors.
In your particular case (if those are your only two files), you don't need it. It's only needed if you had another file that #included file1.h and tried to access i.
It's useful when you have three files:
foo.h
extern int i;
void bar();
a.c:
#include "foo.h"
int i = 6;
int main(){
bar();
}
b.c:
#include "foo.h"
void bar(){
printf("%d\n", i);
}
As you can see, i is shared between both a.c and b.c, not redefined per-file, as would happen without the extern keyword.
The "extern" declaration in C is to indicate that there is an existence of, and the type of, a global variable.
In C mostly each .c file behaves like a seperate module. Hence a variable with "extern" is something that is defined externally to the current module.
It is always a better practise to define the global in one place, and then declare extern references to it in all the other places. When refering to globals provided by any shared library, this is important in order to make sure that your code is referring the correct and common instance of the variable.
From Wikipedia:
When a variable is defined, the compiler allocates memory for that
variable and possibly also initializes its contents to some value.
When a variable is declared, the compiler requires that the variable
be defined elsewhere. The declaration informs the compiler that a
variable by that name and type exists, but the compiler need not
allocate memory for it since it is allocated elsewhere.
Extern is a way to explicitly declare a variable, or to force a
declaration without a definition
If a variable is defined in file 1, in order to utilize the same
variable in another file, it must be declared. Regardless of the
number of files, this variable is only defined once, however, it must
be declared in any file outside of the one containing the definition.
If the program is in several source files, and a variable is defined
in file1 and used in file2 and file3, then extern declarations are
needed in file2 and file3 to connect the occurrences of the variable.
Having extern tells the compiler its a declaration of a variable.
In your example in file1.h imagine what would happen if you didn't specify extern keyword. It will look like there are two definitions of int i. Also, a header file can be included in many .c files. If you compile those .c files and link them, linker would see multiple definitions of the same variable.
extern keyword allows you to say to the compiler ... " Use this variable right now .. I will define and initialize it later ".. i.e " Compile it now .. I will link to its definition later".
You can extern the variable when you define it in some other file and you want to use it in the current context..
The declaration in the header allows you to access the variable from more than one source file, while still only defining it in one place.
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... ;- )