An extern variable located in a function? - c++

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.

Related

Forward declared variable not accessible in cpp file

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.

namespace myspace { int x } Now why `myspace::x=3;` gives error?

Code
#include <iostream>
namespace myspace
{
int x;
}
myspace::x=3; // This line is giving error.
int main()
{
myspace::x=5;
return 0;
}
Output
Error: C++ requires a type specifier for all declarations
So why line myspace::x=3; giving error that C++ requires a type specifier for all declarations ?
The statement
myspace::x=3;
isn't an initialization, it's a plain assignment. It's no different from the
myspace::x=5;
you have inside the main function.
Any statement that isn't a declaration or a definition can't be outside functions.
If you want to initialize the variable, do it at the definition:
namespace myspace
{
int x = 3;
}
You provided a definition upon first declaring the variable. And as others noted myspace::x=3; constitutes an assignment expression at namespace scope, which is not allowed.
If you want to declare the variable without defining it, you need to be explicit and specify it's an extern declaration.
namespace myspace
{
extern int x;
}
The definition would still need the type specifier (as all definitions do), but it will look somewhat like what you imagined
int myspace::x = 3;
While all of this is fine and dandy, global variables (the mutable, run-time external kind) are a code smell. So best not to get in the habit of using them.

c++ Is 'static int' not working across multiple files?

for showing you, I made a very minimalist example of my problem about 1 header and 2 .cpp files. All I do is calling myfunc() and this shall get a value by cin>>. And then main shall print the value (+3). I get the error "a is not defined" for the main.cpp.
I thought static is somehow helping here, but it's not. I don't understand what the problem is.
(I am aware, that I could write cout << myfunc()+3; but it's for a general purpose).
header.h:
#ifndef header_h
#define header_h
int myfunc();
#endif
main.cpp:
#include <iostream>
#include "header.h"
int main()
{
myfunc();
std::cout << a + 3 << std::endl;
}
second.cpp:
#include"header.h"
int myfunc()
{
static int a;
std::cin >> a;
return a;
}
Your a variable is declared inside the function (so it is local to the scope) and hence cannot be accessed outside of it.
If you want access from main, declare it outside the scope of the function (a global variable).
int f() {
int x = 23 ;
return x ;
}
int main() {
std::cout << f() << std::endl ;
std::cout << x ; // Error! x is local to f() and there is no x declared globally or inside main()'s scope.
}
You could do something like this :
int a = myfunc();
std::cout << a ; // Now possible!
Edit: static variable declaration has nothing to do with scoping rules or accessibility. Declaring static merely implies a change in the life-time policy of the variable i.e. its life-time is throughout the program execution duration instead of the duration in which the instructions in the scope (in which the variable is declared) are executed. Thus declaring static does not imply that a variable can be accessed outside of its scope.
"static" does two things: It creates a variable that exists once through the life time of the program, and it makes sure that the variable is accessible by name only in the one compilation unit where it is defined (so if another compilation unit by chance declares something static with the same name, there is no clash).
That means that by design you cannot access a static variable declared in second.cpp from main.cpp. That's absolutely intentional.
In addition, your variable a is declared inside a function. That means it can be only accessed inside that function. So not even code in other functions in second.cpp can access it by name. Again, fully intentional.
Apart from that, if you got around these problems (and you can), storing the result of a function in a global variable and accessing it through that variable is usually considered a very bad programming practice.

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.

Define variables in c++

I am always confused with the concept "define variable." What does define mean?
For example:
void main {
map<int,int> *infoMap;
if() {
//some check here,if it passes this check, then new infoMap
}
infoMap = new infoMap;
}
So does
map<int,int> *infoMap;
or
map<int,int> *infoMap = new inforMap;
define a variable?
The top one is the declaration, or if you like, definition. Here, the compiler allocates space for the variable.
The bottom one is an assignment. Here, the compiler fills the space it allocated at definition time. You can have more than one assignment, if you want to change the value of the variable to something else.
Here's a random, incomplete illustration:
class Foo; // (incomplete forward) class declaration
class Foo { // class definition
int a; // member declaration + definition
int b(int, int); // member function declaration
static int c; // static member declaration
};
int Foo::b(int a, int b) { return a+b; } // member function definition
int Foo::c; // static member defintion
int bar(int); // free function declaration
int main() { // free function declaration + definition
int q; // declaration + definition
q = bar(0);
return q;
}
int bar(int a) { return 2 * a; } // free function definition
Perhaps the "static member definition" is unique in the sense that it provided an actual object instance (i.e. allocation plus construction) for an object that has been declared elsewhere. This is only comparable to a pure-extern declaration:
extern int N; // declaration only, no definition
Not to be confused with a declaration+definition with external visibility:
extern const int M = 11; // declaration and definition
map<int,int> *infoMap;
infoMap is the declaration. Usually when there is initialization along with declaration then it's called defining the variable.
To define something in C++ is to bind an identifier (in this case a pointer to a map<int, int>) to some storage, as opposed to a declaration that only binds an identifier to a type and does not allocate storage. If the compiler does not need any information about the definition of a type (i.e. it only needs the type), then you can get away with just a declaration. Otherwise you need a definition.
With variables define and declare tend to be used interchangeably. However there is a subtle difference.
In most cases you are actually defining the variable.
map<int,int> *infoMap;
The term "define" declares a symbol and gives it substance, storage space for variable, structure/class body, function implementation.
In some instances you can "declare" the variable using the extern keyword. This basically informs the compiler of the existence of the symbol name and its type but does not allocate space for it. The space is allocated elsewhere where the variable is actually defined.
// foo.c
extern int bar;
// bar.c
int bar;
When you declare a variable in c++ you reserve space in memory for it, but the memory is not written to. This declaration happens in
map<int,int> *infoMap;
It could contain anything. When you define the variable you actually set it to some value, in this case a new infoMap.