I have a global int I want to change in different files, for some reason it doesn't work.
I have:
//test.h
#include <windows.h>
static int start1; //want to use this globally.
//declare
void something();
//test.cpp
#include "test.h"
extern int start1;
void something()
{
start1 = start1 + 1;
}
//main.cpp
#include "test.h"
#include "stdafx.h"
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
start1 = 3;
something();
return 0;
}
Why, when you go into something() is start1 0, instead of 3? I have been trying to make a global variable for hours, and it doesn't work. Please can someone clarify?
Don't declare a static variable in a header file. That will result in a separate variable existing for each translation unit (i.e. source file) that includes that header file.
The canonical pattern is to declare the variable as extern in the header file, and then define it "normally" in one source file.
You need to declare your int as extern in your header. It doesn't need any qualifiers when you define it in your .cpp file. The static qualifier actually means that the int you are declaring is only accessible in the current translation unit, so each .cpp file will get a different version of it.
If you put
static int start1;
in all source files, you'll get a static effect, in that the data will be separate addresses within each.
Then you can keep separate values/content for each unit.
BUT. This is NOT a global variable per se. A global variable is one that is shared between units, not the opposite. So there is a difference in static behaviour and global (extern) content... So the above answers are right, but I thought I might add a little perspective to the discussion.
I just ran a similar setup in C, and static variables act the same.
Related
I know global is bad but just as a practice, is this the correct way to initialize a global class used between multiple object files?
Header 1.h
class test {
int id;
public:
test(int in){
id = in;
}
int getId(){
return id;
}
};
extern test t;
File 1.cc:
#include <iostream>
#include "1.h"
int main(){
std::cout << t.getId() << std::endl;
return 0;
}
File 2.cc:
#include "1.h"
test t(5);
Now what if instead of extern I use the static approach globally static test t(0); in the header?
Correct me if I'm wrong but that would compile fine however I would have 2 different unrelated copies of the same t in both object files and the final binary? Is that bad? Or does the linker sort it out to eliminate multiple copies?
There are global instances, not global classes.
What you have is a global instance. And yes, this sounds about right, until you get to multiple global instances which depend upon each other. Then the real fun will start.
Defining a variable as 'static' at global level means the variable will be defined in the compilation unit only (i.e. the '.o' file) and the symbol won't be exported by the compiler.
In other words: yes, there will be multiple variables with the same name but only visible to functions on the same compilation unit.
Besides, 'invisible' doesn't mean 'inaccessible'. You still can provide access to the variable. For example:
1.h
struct Test { int value; }; // Class definition
Test& get_t(); // Function declaration
1.cc
#include "1.h"
static Test t; // Variable declared as 'static'
Test& get_t() { return t; };
2.cc
#include "1.h"
#include <iostream>
int main()
{
std::cout << get_t().value << std::endl; // Static variable accessed
}
I use the static approach globally static test t;?
But your test class needs an int in parameter for the constructor, so you want:
static test t(0); // or whatever int you want
If you turn the extern to static in the header, you would define a static variable in each compilation unit in which the header is imported. So classes in different cpp files would no longer "communicate" via t, since each would have theirs. This is very error prone.
In addition, adding the definition of a static in a header is an extremely bad practice. When someone includes a header, one does not expect that it will create variables.
Including the declaration of t as extern is an acceptable practice. But be aware that if the header has a general purpose, this might reduce its reusability other projects.
More information of interest for you:
Must read: C++ Core Guidelines about source files
Must read: Guidelines for writing headers
StackOverflow: When are global variables recommended
Why global variables should be avoided if possible and when are they ok
If you put a variable declaration outside of any function, you're declaring the variable as 'global'. Ex:
1.cc
int this_is_global;
From here on you can use the variable in any function of '1.cc'.
For using the same variable in any other file, the compiler will need to know about it:
2.cc
extern int this_is_global;
Here, the keyword extern tells the compiler that the variable is declare somewhere else, letting the task of finding it to the linker.
If you miss to add the extern keyword here, the compiler will treat it as a new variable, and the linker will have two variables with the same name and will emit an error. All of your source files of your project except the first one will need the extern keyword to avoid duplicate symbols.
So common practice is to add the 'extern' declaration in an include file:
1.cc
int this_is_global;
1.h
extern int this_is_global;
2.cc
#include "1.h"
On the other side, the static keyword tells the compiler not to export the symbol. In other words: the variable will exists only in the source file it is declared. You could declare it once per source file and there will be different variables with the same name. Ex:
1.h
static int my_var;
1.cc
#include "1.h"
2.cc
#include "1.h"
This way, you'll end having two variables 'my_var' and changes to any of them won't affect the other.
This is the most confusing part for me from section Global Variables and linkage properties.
extern int g_var1;
Statement could be something like this when defining an external non-const global variable. I think I will write exactly the same for using that variable (through forward-declaration) in some other file. If both the statements are same, how C++ knows whether the variable was declared or was defined in a file?
If I understand your question correctly, you shouldn't write exactly the same in another file (namely, you shouldn't write "extern int g_var1" in two files). A good practice is to declare some variable global in a header file; make the definition in a cpp file that includes this header file. After doing this, you can use this variable in all of the files that will include the header file.
To illustrate, an example would be something like this:
variables.hpp
#pragma once
extern int g_var1;
variables.cpp
#include "variables.h"
int g_var1 = 1;
main.cpp
#include "variables.h"
#include <iostream>
using namespace std;
int main(){
cout << g_var1 << endl;
}
A statement of the form
extern int g_var1; // this is a declaration
is a declaration of a variable. The keyword extern makes sure of this.
If you write
int g_var1; // declare and define variable
you define it as well. You can declare a variable as many times as you like, but define it only once. You could therefore write
extern int g_var1;
in those files where you need to use the variable. Then during linking the compiler will resolve the definition of the variable (provided that you give the definition in some file of course).
When you say extern int g_var1; the variable is just declared, and later when you have to use it you can use it directly.
file1.cpp:
int g_var1;
File2.cpp:
extern int g_var1;
You need not to write extern everytime.
Though i would suggest if you have to use global variables place them in a separate header file.
I have a global int I want to change in different files, for some reason it doesn't work.
I have:
//test.h
#include <windows.h>
static int start1; //want to use this globally.
//declare
void something();
//test.cpp
#include "test.h"
extern int start1;
void something()
{
start1 = start1 + 1;
}
//main.cpp
#include "test.h"
#include "stdafx.h"
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
start1 = 3;
something();
return 0;
}
Why, when you go into something() is start1 0, instead of 3? I have been trying to make a global variable for hours, and it doesn't work. Please can someone clarify?
Don't declare a static variable in a header file. That will result in a separate variable existing for each translation unit (i.e. source file) that includes that header file.
The canonical pattern is to declare the variable as extern in the header file, and then define it "normally" in one source file.
You need to declare your int as extern in your header. It doesn't need any qualifiers when you define it in your .cpp file. The static qualifier actually means that the int you are declaring is only accessible in the current translation unit, so each .cpp file will get a different version of it.
If you put
static int start1;
in all source files, you'll get a static effect, in that the data will be separate addresses within each.
Then you can keep separate values/content for each unit.
BUT. This is NOT a global variable per se. A global variable is one that is shared between units, not the opposite. So there is a difference in static behaviour and global (extern) content... So the above answers are right, but I thought I might add a little perspective to the discussion.
I just ran a similar setup in C, and static variables act the same.
FileA.hpp:
static int a;
void change(int);
FileA.cpp
#include "FileA.hpp"
void change(int x) { a = x; }
main.cpp
#include "FileA.hpp"
#include <cstdlib>
#include <iostream>
int main()
{
a = 5;
std::cout<<a<<std::endl;
change(10);
std::cout<<a<<std::endl;
a = 20;
std::cout<<a<<std::endl;
system("Pause");
return 0;
}
My output is:
5
5
20
Can someone help me with this? Why variable 'a' don't want to change in function
which is in FileA.cpp.
How to fix this. When I make change(int x) inline in "FileA.hpp" it works fine.
The static keyword on a global variable gives that variable internal linkage. It means that any translation unit that has that definition will have its own copy of the object. So the a object that main.cpp sees and that FileA.cpp sees are different objects. change will modify one of them, but main will output the other.
If you were intending static to mean that the object has static storage duration, global variables (or variables at namespace scope in general) have static storage duration anyway. You don't need to mark them static. However, if you remove static, you'll have another problem; you'll have multiple definitions of a across translation units.
The correct way to do this is to declare a as extern in the FileA.hpp file:
extern int a;
Then in a single translation unit (probably in FileA.cpp, define the object:
int a;
This means that any object that includes FileA.hpp will have the declaration of a (which is fine) and only one translation unit will have the definition of a. Perfect.
You declare a in the header file, which when included creates two copies of it, one in main.cpp and one in FileA.cpp. When you do a = 5; you assign to the copy from main.cpp, while when calling the function change, it changes the copy in FileA.cpp.
I have 4 files:
shared.h
main.cpp
something.h
something.cpp
shared.h:
#ifndef SHARED_H
#define SHARED_H
int* sth;
#endif
something.h:
#ifndef SOMETHING_H
#define SOMETHING_H
class foo
{
public:
void printVar();
};
#endif
something.cpp:
#include <iostream>
#include "something.h"
#include "shared.h"
using namespace std;
void foo::printVar()
{
cout<<"Foo: "<<*sth<<endl;
};
main.cpp:
#include <cstdlib>
#include <iostream>
#include "shared.h"
#include "something.h"
using namespace std;
int main(int argc, char *argv[])
{
sth=new int(32);
foo x;
cout<<"Main: "<<*sth<<endl;
x.printVar();
system("PAUSE");
return EXIT_SUCCESS;
}
Compiler returns multipe definition of *sth;
I added static modifier to the *sth and it compiles, but crashes. I changed the printings to print the adresses of pointer and I had program returned:
Main: 0x3e0f20
Foo: 0
Why is the foo's pointer not assigned? I want to assign it only once in main and then share in other files... How can I do this? Is it something with extern modifier?
Thanx for any replies.
In shared.h you want to say:
extern int* sth;
to promise the compiler that sth exists somewhere.
Then in one (and only one) of the .cpp files you need to write:
int* sth;
To make it actually exists. In general you probably want to read about the difference between declaration and definition. As a rule of thumb you only want to declare things in header files, not define them.
When you wrote static previously you said that a variable with the same name exists in every file, but is "local" to each, i.e. the sth in main.cpp won't be the same as the sth in something.cpp.
Yes, use extern. Put extern int* sth; in the header, and then in one of the source files put int* sth;.
extern tells the compiler and linker that the actual variable/function definition is in another compilation unit (i.e. another source file).
You need to mark sth as extern in the header to make it a declaration, and provide a definition for it in one of the cpp files. Otherwise, the variable is declared in each compilation unit where the header is included, which is not the effect you are looking for.
P.S. I assume that you know why global variables are not good, right?
"I have 4 files".
Let me stop you right there. I agree that you have four files, but that's not really relevant. You have two translation units. A translation unit is the quantum of text that is fed into your compiler. Your translation units, let's call them MAIN and SOMETHING, consist of the result of preprocessing your files main.cpp and something.cpp, respectively.
After preprocessing, each of your translation units includes a line int *sth; This line declares and defines the variable sth.
The one-definition-rule requires that you have, in your entire program, exactly one (not more, not fewer) definition of sth. In order to accomplish this, you must have exactly one source-code line int *sth; in exactly one translation unit, and as many extern int *sth; as you require.
In your case, I would put int *sth; in MAIN and extern int *sth; in SOMETHING. Additionally, you can have as many extra copies of extern int *sth; as you feel like -- they won't hurt anything.
Now, back to your four files. You should put extern int *sth; in shared.h. This means that MAIN and SOMETHING will both have an extern line in them. You should also put int *sth; in main.cpp, so that MAIN will have the definition.
And there you are: MAIN and SOMETHING both have extern lines, so they are both referring to the same variable. MAIN also has a definition. so the sth variable has exactly one of those.
Aside: Why does static int *sth; in shared.h do the wrong thing?
Because each of the two translation units see their own static declaration. A static declaration reduces the linkage of the declared name to that single translation unit.
You don't want to make it a static global as that will create a local sth in every translation unit and you are only allocating it in one. This is why it crashed in Foo::printVar as in that scope it was an uninitialized pointer.
You want to declare it as extern int* sth; in the shared header then put int* sth; before main or in at least one place before it's used.
Actually, if you really need a globally accessible object, allocated on the heap, and you want to share it then it may be better as extern std::shared_ptr<int> sth;. Define it as std::shared_ptr<int> sth; the same way in one of the CPP files and call std::make_shared to allocate it. This way deallocating the memory will be handled automatically when the last object that uses it goes out of scope.