Identification problem in variables belonging to extern storage class - c++

a.cpp
extern int var;
int func(){
return var;
}
main.cpp
#include <iostream>
using namespace std;
extern int func();
int main(){
int var = 12;
cout << func();
}
When I write as above, I get this error "undefined reference to var".
a.cpp
extern int var;
int func(){
return var;
}
main.cpp
#include <iostream>
using namespace std;
extern int func();
int var = 12;
int main(){
cout << func();
}
But when I make the above change in the main.cpp file, the application compiles without any problems and 12 is printed on the screen.
Why does this problem occur?

Well, you never know if it's a troll, but in short, your first set of functions declare var as a local variable, within the scope of main() only. As such you may not reference it in a.cpp. Imagine if you did... the lifetime of var is (strictly) temporary (irrespective of being in the "main" function) and is not reserved in RAM, and as such the compiler will not allow the use of extern in a.cpp... what address could it use?
The second time you correctly declare var as a global, within main.cpp. As such your extern in a.cpp is valid, and you can thus reference var. In this case var is reserved in RAM, and accessible from files that declare it extern.
A good explanation of scope is available at tutorialspoint, and here at cplusplus.

In the first case, the variable is local to function main(). You cannot reference such local variables from other functions.
In the second case it is a global variable. That works.

Related

How to access local static variables and local variables inside a function from other files in C/C++ programming?

file1.c
int b=2;
void func(){
int c=10;
static int d=10;
int *cp=&c;
}
main.c
#include <stdio.h>
#include <stdlib.h>
extern b;
extern *cp;
int main()
{
int a=1;
printf("a=%d\nb=%d\n",a,b);
printf("c=%d\nd=%d\n",c,*cp);
return 0;
}
I couldn't able to access local variable 'c' from other file using pointe '*cp' as well.
I know by default we can access the functions from other files without using extern keyword but how to access the local variables and static variables present inside those functions ?
It is not possible. The variables in that function are scoped for use only in that function. However if you made variable c a static one, you could make a global pointer, declared in the same place as b. Then you could declare a extern int *ptr_to_c in main.c and be able to access the variable c through pointer access.
```c
file1.c
int b=2;
void func(){
// local scope, stored ok stack, can only be accessed in this function
int c=10;
// stored in RAM, can only be accessed in this function
// but if you take a pointer to it, it will be valid after this function executes
static int d=10;
// the pointer itself, cp is stored on stack and has local scope
int *cp=&c;
}
main.c
#include <stdio.h>
#include <stdlib.h>
// this will allow you to access "b" in file1.c
// it should read: extern int b;
extern b;
// you will probably get link errors, this does not exist
extern *cp;
int main()
{
int a=1;
printf("a=%d\nb=%d\n",a,b);
printf("c=%d\nd=%d\n",c,*cp);
return 0;
}
```
You could do this:
file1.cpp
int * cp =0;
void func() {
static int c;
// store c's adress in cp
cp = &c;
}
main.c
extern int *cp;
int main()
{
// you need to call this otherwise cp is null
func();
*cp = 5;
}
However, this is very bad c code. You should simply declare int c with file scope in file1.c exactly like b.
In practice, if you think you need static variables inside a function you should stop and reconsider.

Difference between defining globally and within scope

So, I have a variable declared globally. For it to be used, it has to be defined. I get different results based on whether I define it globally or within scope of the main function.
Here's the basic code:
// main.cpp
//int variable = 3;
int main()
{
//int variable = 5;
func();
return variable;
}
// source.cpp
#include "source.hpp"
void func()
{
cout << variable << endl;
}
// source.hpp
#ifndef __SOURCE_HPP_INCLUDED__
#define __SOURCE_HPP_INCLUDED__
#include<iostream>
using namespace std;
extern int variable;
void func();
#endif // __SOURCE_HPP_INCLUDED__
So, if I define globally (outside main), then everything works. But if I define within main, then I get "undefined reference to 'variable'" errors. But I only call upon source.cpp when I'm inside main; so why do I get this error, if variable is defined within the same "scope" as func? Is it the compiler just preemptively giving the error before linking is done? Or is it related to the fact that I declared it as "extern"?
You can't define a global variable inside a function. You're actually defining a different, unrelated local variable that just happens to have the same name.
func references the global variable, so you must have a definition for it.

Do inline namespace variables have internal linkage? If not, why does the code below work?

This question is directly related to this one. Consider the code:
#include <iostream>
inline namespace N1
{
int x = 42;
}
int x = 10;
int main()
{
extern int x;
std::cout << x; // displays 10
}
It displays 10. If I remove the extern int x; declaration then we get an ambiguity compiler time error
error: reference to 'x' is ambiguous
Question: why does the code work with the extern int x declaration work, and why does it stop working when I remove it? Is it because inline namespace variables have internal linkage?
No. There is no provision in [basic.link] that would cause x to have internal linkage. Specifically, "All other namespaces have external linkage.", and "other" refers to "not unnamed". Perhaps you were thinking of unnamed namespaces?
No, the code works because to avoid breaking existing C code, extern int x; has to work the same way in did in C, in other words creating a local extern to a global namespace (that's all we had in C) variable. Then when you use it later the locally declared extern removes any possible ambiguity.

Trying something simple with extern

I am trying to learn what "extern" does. I have a simple program where in main's header, a variable is declared with extern. In main, that variable is defined. Main then calls a method in another class file (that includes main's header so it should have access to the external variable), in order to print the value of that variable. But I get a compiler error: "unresolved external symbol "int myglobal". Can someone help? Thanks!
The code runs fine if I remove the reference to this variable in the source.cpp file.
source.cpp
#include "main.h"
#include <iostream>
void printGlobal()
{
std::cout << "Global: " << myglobal;
}
source.h
void printGlobal();
main.h
extern int myglobal;
main.cpp
#include "main.h"
#include "Source.h"
int main()
{
int myglobal = 5;
printGlobal();
system("pause");
return 0;
}
extern only works with global scope. if I say extern int myint; that means there is a file somewhere that has int myint; outside any function this is global scope
there is also file scope which is via static int myint; that means other files won't be able to access it via extern
change main.cpp to
#include "main.h"
#include "Source.h"
int myglobal = 5;
int main()
{
printGlobal();
system("pause");
return 0;
}
for file scope
#include "main.h"
#include "Source.h"
static int myglobal = 5;
int main()
{
printGlobal();
system("pause");
return 0;
}
extern and static keywords are storage specifiers. Each storage specifiers basically add two properties to a name:
1. Allocation or deallocation of name.
2. Visiblity.
If you add "extern" keyword to name in "C", it only declares a variable so that you can use that name in your program without compiler error. Means extern variable are visible outside the scope where they are defined. This symbol also instructs the linker to find the symbol definition in other object files. Therefore in your case when you added "extern" to myGlobal, you only declared a variable with name "myGlobal " and could use that name in your program. But when linker came, it tried to find the place where that "myGlobal" is defined, but it was unable to find this and gave you "unresolved external symbol" error.
All extern(global) variables are allocated when the program starts and destroyed when program ends.
Another use of "extern" other than what A.H. provided:
test1.c
int myextern = 10;
test2.c
void func1(){
int extern myextern;
printf("%d",myextern);
}
Static:
Allocation/Deallocation of static variables are same as extern variable. Means they are allocated when the program starts and destroyed when program finished. But visibility of the static variables are limited to the lexical scope where they are declared. They are not visible outside their scope.

Not able to understand static behaviour

I wrote in
// In file t.h
#ifndef __t_h__
#define __t_h__
static int abc;
#endif
--
//In main.c
#include <stdio.h>
#include "t.h"
int main()
{
abc++;printf("%d \n", abc);
test();
}
- -
//In test.c
#include <stdio.h>
#include "t.h"
void test()
{
abc++;
printf("%d \n", abc);
}
When I run the project I found the output of abc is 1 and 1.
But when I change it to int abc in t.h. The output of abc = 1 and 2.
Why static is not retaining the value when the control reaches to test.c file.
If it won't retain then why should not it provide an error as the static variable can not be shared between/among the files?
static variables has internal linkage which means each translation unit gets its own copy.
So in your program each .cpp file which includes t.h has its own copy of the static variable, which in turn means, there are two objects in the memory. You can try printing their addresses to confirm this, as they will be different.
That makes the situation pretty simple: if you change the object in one .cpp, it doesn't reflect in the other .cpp file, because the object in the other .cpp file is a different object. Why should it change?
But when you change it to int abc (i.e don't make it static), then each translation unit has same object. If you change it in one file, it will be reflected in other file also, as expected.
As for sharing, then yes, static objects can be shared between two functions in the same translation unit, but they cannot be shared between two translation units.
Search for translation unit on this site, you will get many topics on it. Read them, then you will understand it fully.
When the preprocessor is done with your code, main.c looks like
// omitted stuff from stdio
static int abc;
int main()
{
abc++;printf("%d \n", abc);
test();
}
and test.c looks like
// omitted stuff from stdio
static int abc;
void test()
{
abc++;
printf("%d \n", abc);
}
So each file contains its own variable abc that is not accessible from the other.
One solution would be to change t.h to
#ifndef __t_h__
#define __t_h__
extern int abc;
#endif
and then change main.c to
#include <stdio.h>
#include "t.h"
int abc;
int main()
{
abc++;printf("%d \n", abc);
test();
}
You can think about it like this: there's now only one int abc in your program, in main.c but test.c knows about its existence because the extern int abc tells test.c that somewhere else in the project there is an integer called abc that it will be able to find at link time.
When you declare a static variable in header file a copy of the static variable is created in each Translation unit where the header is included. So each of the translation units involved in your program has its own copy of abc now and hence you get the observed behavior.The behavior is not what you expected but it well defined one.
static variable can not be shared between/among the files?
No they cannot be! that is the very purpose of making them static
static variables have internal linkage. Their scope is restricted to the the translation unit in which they are declared. They cannot be accessed beyond the TU.If you want to share the same variable across different Translation units You should drop the static and use extern, which gives the variable an external linkage and hence visibility across different translation units.
Good Read:
How do I use extern to share variables between source files?
In C, static has two usages:
1, Use static keyword to limit the var's scope in the translation unit. To make this simple, if you have two files: a.c, b.c and you wrote:
static int varA;
in a.c, then this means varA could only be used in a.c, if you want to use varA in b.c, you should remove the static keyword, and add extern int varA; in b.c, what people usually do is we create another file called: a.h, and write extern int varA; in a.h, and we simply include "a.h" in b.c, so we could write every variable we want to extern in a.h and use a single include "a.h" to make these variables or functions legal in other .c files(i.e. source files)
2, Using static to define a local variable in a function, for instance:
int TheFunction()
{
static int var = 0;
return ++var;
}
Because you used the static keyword on a local variable var, this variable will not loss when TheFunction() is returned.
The first time you call TheFunction() you will get 1, the second time you call TheFunction() you will get 2, and so on.
Next, lets see the usage of static in C++.
Because any C++ complier can complie a C code, so the 2 usages above is also in C++.
another two usages is:
1, static member variable.
2, static member function.
Lets see the code directly:
#include <iostream>
using namespace std;
class Test
{
public:
Test() : m_nNormalVar(0)
{
}
public:
// You need to init this static var outside the class
// using the scope operator:
// int Test::m_nStaticVar = 0;
static int m_nStaticVar;
// You can init this const static var in the class.
const static int m_nConstStaticVar = 10;
// This is just a normal member var
int m_nNormalVar;
};
int Test::m_nStaticVar = 0;
int main(int argc, char *argv[])
{
Test a;
Test b;
a.m_nStaticVar++;
a.m_nNormalVar++;
cout << b.m_nStaticVar << endl;
cout << b.m_nNormalVar << endl;
return 0;
}
a and b are objects of class Test they have the same m_nStaticVar and the same m_nConstStaticVar, but they have their own m_nNormalVar this is a static member variable.
#include <iostream>
using namespace std;
class Utility
{
public:
// This is a static member function, you don't
// need to have a concrete object of this class
// to call this function.
static int SelectMax(int a, int b)
{
return a > b ? a : b;
}
};
int main(int argc, char *argv[])
{
// No objects of class Utility
cout << Utility::SelectMax(2, 1) << endl;
return 0;
}
So this is a static member function of a class in C++.
These four ways of static's usage is all I known, if there are still some other usages, please help to edit this post, thx:)
EDIT:
Add static global function
1, Use static keyword to limit the function's scope in the translation unit. To make this simple, if you have two files: a.c, b.c and you wrote:
static void StaticFunction();
in a.c, so you can only call StaticFunction() in a.c, if you want to call this function in b.c you should remove the static keyword and then delcare it before the usage. Or just declare it in a.h and include "a.h" in b.c