Forward declared variable not accessible in cpp file - c++

Considering the example below:
header.h
extern int somevariable;
void somefunction();
source.cpp
#include "header.h"
somevariable = 0; // this declaration has no storage class or type specifier
void somefunction(){
somevariable = 0; // works fine
}
I couldn't find the answer to the following questions:
Why can't I just forward declare int somevariable and initialize it in the .cpp file?
Why is the somefunction() function able to "see" somevariable when declared using extern int somevariable, and why is it not accessible outside of a function?

extern int somevariable;
means definition of somevariable is located somewhere else. It is not forward declaration. Forward declaration is used in context of classes and structs.
somevariable = 0;
is invalid since this is assignment and you can't run arbitrary code in global scope.
It should be:
int somevariable = 0;
and this means define (instantiate) global variable somevariable in this translation unit and initialize it to 0.
Without this statement linking of your program will fail with error something like: undefined reference to 'somevariable' referenced by ... .
Use of global variable in any langue is considered as bad practice, sine as project grows global variable makes code impossible to maintain and bug-prone.

Related

Use of extern in C++ dll

I declare then instantiate a static variable in a DLL.
// DLL.h
class A
{
//...
};
static A* a;
// DLL.cpp
A* a = new A;
So far, so good... I was suggested to use extern rather than static.
extern A* a; // in DLL.h
No problem with that but the extern variable must be declared somewhere. I got Invalid storage class member.
In other words, what I was used to do is to declare a variable in a source file like this:
// In src.cpp
A a;
then extern declare it in another source file in the same project:
// In src2.cpp
extern A a;
so it is the same object a at link time. Maybe it is not the right thing to do?
So, where to declare the variable that is now extern?
Note that I used static declaration in order to see the variable instantiated as soon as the dll is loaded.
Note that the current use of static works most of the time but I think I observe a delay or something like this in the variable instantiation while it should always be instantiated at load time. I'm investigating this problem for a week now and I can't find no solution.

How does extern work?

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.

An extern variable located in a function?

According to wikipedia:
http://en.wikipedia.org/wiki/External_variable
An external variable may also be declared inside a function.
What is the purpose of an extern variable being declared within a function? Would it have to be static too?
It allows for restricting access to a global to some scope:
int main()
{
extern int x;
x = 42; //OKAY
}
void foo()
{
x = 42; //ERROR
}
int x;
The external declaration goes inside a function. It simply means that no other functions can see the variable.
void func()
{
extern int foo;
foo ++;
}
void func2()
{
foo--; // ERROR: undeclared variable.
}
In another source file:
int foo; // Global variable. Used in the other source file,
// but only in `func`.
It is just a way to "isolate" a variable, so it doesn't accidentally get used in places where it isn't supposed to be used.
The only difference between declaring an external variable at namespace scope:
extern int x;
void foo() {
cout << x;
}
and declaring it at function scope:
void foo() {
extern int x;
cout << x;
}
is that in the latter case, x is only visible inside the function.
All you're doing is further tightening the scope of the extern declaration.
Here's an analogous example using namespaces:
At namespace scope:
#include <string>
using std::string;
void foo() {
string str1;
}
string str2; // OK
At function scope:
#include <string>
void foo() {
using std::string;
string str1;
}
string str2; // Error - `using` not performed at this scope
The extern keyword says that an identifier has external linkage. This means that it is linked to the same name anywhere else it is declared with external linkage. That is, the different instances of the name in different places refer to the same object.
Declaring an identifier inside a block (including the block that defines a function) gives it block scope. The scope of that instance of the identifier ends at the end of the block.
Combining extern with block scope allows a function to see an external identifier without cluttering the name space of other functions. (Nonetheless, it is often bad practice.)
The text refers to a non-defining declaration of an extern variable inside function. Extern definitions inside functions are illegal.
So, a non-defining declaration of an extern variable inside function simply means that you want to use that variable inside that function. The variable itself must be a global variable defined elsewhere.
Basically, if you don't need access to that global variable (defined elsewhere) in the entire translation unit and just need it inside that function, it is perfectly good idea to declare it locally. That way you are not polluting global namespace with identifiers no other function needs.

How to declare a global variable in C++

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... ;- )

scope of non-member, non static variables and methods

Test.h
class Test
{
public:
Test();
//some methods
private:
int var;
//some vars
}
Test.cpp
#include "Test.h"
int a;
void func()
{
//some code here
}
Test::Test()
{
//some code
}
Variable a and function func() are non-member and non-static.
What is the lifetime of variable a and function func()?
Consider Test class as a part of a shared library. Can other classes of that library access a or func() by resolution operator ?
What is difference between static declaration of variable a/ func() and nonstatic declaration of a/func() ?
Variables and functions have the same scope: they exist from their point of declaration onward.
This is relatively different from attributes and methods of a class whose scope is limited to the class itself and where order matters less (though it may... for types).
The MSDN page is the answer to your question. It defines scope and Lifetime.
a have scope and life time through out the file since its global.
func() doesnt have scope or lifetime. they only have visibility.
if its part of shared library also functions and global variables can be accessed by other parts provided library is visible.
In this case being static doesnt make much of a difference. But local variables when made static gets global scope but will have only local visibility.
Variable a is a global variable, its scope is entire program runtime i.e its created during your program startup and destroyed during program exit. func is a global function and functions do not have any concept of scope attached to them.
In C++ a scope, defined by C++11 ยง3.3.1/1, is a (possibly discontiguous) region of text where a name can be used unqualified to refer to the same entity.
A potential scope is the scope a name will have when there are no declarations of the same name within the potential scope.
The scope of your variable name and function name extends from the declaration, to the end of the file.
Variable "a" is a global variable to Test.cpp
and "func" is a normal function in Test.cpp.
Edit section:-
But u can use the same variable & method in different place if u do the same as listed below.
//file1.h
#ifndef FILE1_H
#define FILE1_H
extern int a;
extern void func();
#endif
//end of file1.h
//file1.cpp
#include"file1.h"
int a; // a=0 as it is global variable
static int x = 10;// Scope is limited, it can only be used in file1.cpp
static void func2(){
int z = x;
z = x+z;
//... some thing u r doing
}
void func(){
//... some thing u r doing
}
//end of file1.cpp
//file2.cpp
#include"file1.h"
//U can use variable "a" & method "func" defined in file1.cpp . For an eg:-
int add(int b){
func();//func defined in file1.cpp but used here
//func2(); //It will throw error if you remove the comment before func2 method as
//the scope of func2 is limited to file1.cpp as it is static method
return a+b;// a defined in file1.cpp but used here
}
int main(){
//some code exists here
return 0;
}
//end of file2.cpp
//================
There are lot of things by which u can play around. It just one of the example.
Like if you declare static global variable then scope of that variable is limited to that file only.
Variable "a" & "func" is accessible by other classes present in the same file where the Test Class is present.
If you declare any variable or method as static global variable then the scope of that variable & method is limited to that file as explained in above example.