Using the same variable across multiple files in C++ - c++

In the process of changing some code, I have spilt some functions into multiple files. I have the files controls.cpp and display.cpp and I would like to be able to have access to the same set of variables in both files. I don't mind where they are initialized or declared, as long as the functions in both files can use them.
This was not an issue when the functions were in the same file, but now it seems almost impossible after an hour of googling and trying various things.

Define the variable in one file like:
type var_name;
And declare it global in the other file like:
extern type var_name;

use those variables as extern
i.e.
extern int i;
in another file declare same as normal global variable...
int i;//global

Create two new files:
Something like Globals.h and declare all variables like: extern type name;
btw remember include guards.
Something like Globals.cpp and declare variables like: type name;
Then add #include "Globals.h" at the top of:
Globals.cpp
controls.cpp
display.cpp
You may then want some functions to initialise them.

Essentially all you have to do is declare the variable once in one code file, and declare it in the others as extern (making sure NOT to initialize it when you are declaring it extern, or some compilers will ignore the extern keyword, giving you compiler errors.)
The simplest way to do this is to use a macro in a header file, like such:
#pragma once
#ifdef __MAIN__
#define __EXTERN(type, name, value) type name = value
#else
#define __EXTERN(type, name, value) extern type name;
#endif
and then declare your variables in that same header file, like such:
__EXTERN(volatile int, MyVolatileInteger, 0);
from any ONE file in the project, include the header file, like such:
#define __MAIN__
#include "Globals.h"
from all the rest, just simply include it normally, like such:
#include "Globals.h"
Presto, you're done. Variables only declared once, and initialized in-line. This is very maintainable, and saves you the trouble of having to declare everything twice.

All of the declarations you want visible in multiple compilation units (.cpp files), should go into a header file that you include in all places that need to use the variable, type, class, etc.
This is vastly better than extern, which essentially hides your intention to share the declaration.

Related

Understanding C linker error: multiple definition

I have a project with multiple header files and .cpp files.
All of the header files have include guards.
There is a file called Constants.h where I define some constants. Some of these with defines, some as constant variables.
There are more header-.cpp-file pairs with code in them. One of these does contain a class, the others don't.
When I include my files into my main file (an arduino sketch), I get a lot of linker errors, claiming there are multiple definitions of some variables.
I read that this mainly occurs when you include .c or .cpp files, which I don't do. All the .cpp files only include their appropriate header files.
I did manage to find multiple solution proposals:
1) inline:
With functions, inline can be used to get rid of this problem. However, this is not possible with variables.
2) anonymous namespace:
This is one of the solutions I used. I put anonymous namespaces around all the problematic definitions I had. It did work, however I do not understand why this works. Could anyone help me understand it?
3) moving definitions into .cpp files:
This is another approach I used sometimes, but it wasn't always possible since I needed some of my definitions in other code, not belonging to this header file or its code (which I do admit is bad design).
Could anyone explain to me where exactly the problem lies and why these approaches work?
Some of these with defines, some as constant variables.
In C const does not imply the same thing as it does in C++. If you have this:
const int foo = 3;
In a header, then any C++ translation unit that includes the header will have a static variable named foo (the const at namespace scope implies internal linkage). Moreover, foo can even be considered a constant expression by many C++ constructs.
Such is not the case in C. There foo is an object at file scope with external linkage. So you will have multiple definitions from C translation units.
A quick fix would be to alter the definitions into something like this:
static const int foo = 3;
This is redundant in C++ but required in C.
In addition to Story Teller's excellent explanation, to define global variables, use the following:
// module.h
#include "glo.h"
// glo.h
#ifndef EXTERN
# define EXTERN extern
#endif
EXTERN int myvar;
// main.c
#define EXTERN
#include "glo.h"
In main.c all variables will be declared (i.e. space is allocated for them), in all other c files that include glo.h, all variables will be known.
You shouldn't declare any object in header files, this should be moved to c\c++ files.
In header you may:
declare types such as: classes, structs, typedefs etc.
put forward declarations of (not classes) functions
put inline (or in classes) functions (+ body)
you may add extern declaration.
you may put your macros.
a static declaration may declare things multiple times, therefore it is not recommended.

Definition and declaration of global variables using preprocessor trick

I am currently looking through the code written by senior engineer. The code works fine but i am trying to figure out one detail.
He uses quite a few global variables and his code is broken down into a lot of separate files. So he uses a technique to make sure that global vars are declared everywhere where he needs to access them but are only defined once.
The technique is new to me but I read few articles on the internet and got some understanding about how it works. He uses
#undef EXTERN
followed by conditional definition of EXTERN as an empty string or actual extern. There is a very good article here explaining how it works. Also there is a discussion here
What gets me confused is that all examples I saw on the web suggest to include header file in a regular way in all of the source files that need it except for one. In this single special case line that includes header is preceded by definition of a symbol that will ensure that EXTERN will be defined to an empty string and .. so on (see link above). Typically this single special case is in main or in a separate source file dedicated to the declaration of global variables.
However in the code that I am looking at this special case is always in the source file that corresponds the header. Here is the minimal example:
"peripheral1.h" :
#undef EXTERN
#ifndef PERIPHERAL_1_CPP
#define EXTERN extern
#else
#define EXTERN
#endif
EXTERN void function1(void);
"peripheral1.cpp" :
#define PERIPHERAL_1_CPP
#include "peripheral1.h"
function1()
{
//function code code here
}
Everywhere else in the code he just does
#include "peripheral1.h"
My question is how and why does that work? In other words, how does compiler know where to define and where to just declare function (or variable, or class ...)? And why is it ok in above example to have the lines :
#define PERIPHERAL_1_CPP
#include "peripheral1.h"
in actual peripheral1.cpp rather then in main.cpp or elsewhere?
Or am I missing something obvious here?
All the source files, except "perripheral1.cpp", after preprocessing contain a sequence
of external variable declarations like:
extern int a;
extern int b;
extern int c;
In peripheral1.cpp only, after preprocessing, there will be a sequence of declarations:
int a;
int b;
int c;
int d;
which are tentative definitions of the corresponding variables, which, under normal circumstances are equivalent of the external definitions :
int a = 0;
int b = 0;
int c = 0;
int d = 0;
End result is, variable are declared everywhere, but defined only once.
PS. To be perfectly clear ...
In other words, how does compiler know where to define and where to
just declare function (or variable, or class ...)?
The compiler knows where to declare, whenever it encounters a grammatical construct, which is defined in the standard to have the semantics of a declaration.
The compiler knows where to define, whenever it encounters a grammatical construct, which is defined in the standard to have the semantics of a definition.
In other other words, the compiler does not know - you tell it explicitly what you want it to do.
Nostalgia
Ahh, this takes me back a fair way (about 20 years or so).
This is a way for C code to define global variables across multiple files: you define the variable once using a macro to ensure it is defined exactly only once, and then extern it in other C code files so you can utilise it. Nowadays it is quite superfluous in many instances, however it still has its place in legacy code, and will (most likely) still work in many modern compilers, nut it is C code not C++.
Normally the likes of #define PERIPHERAL_1_CPP is utilised to ensure uniquenesss of inclusion like a #pragma once
In my own code I would use something like:
#ifndef PERIPHERAL_1_CPP
#define PERIPHERAL_1_CPP
// my includes here
// my code here
#endif
That way you can #include the file as many times as you want all over your code, in every code file even, and you will avoid multiple definition errors. To be fair I normally do it with the .h files and have something like:
// for absolutely insane safety/paranoia
#pragma once
// normally sufficient
#ifndef PERIPHERAL_1_H
#define PERIPHERAL_1_H
// my includes here
// my code here
#endif
I have never tried it on cpp files but wil llater tonight to see if there is any benefit one way or the other:)
Give me a shout if you need any more info:)

Access extern variable in C++ from another file

I have a global variable in one of the cpp files, where I am assigning a value to it. Now in order to be able to use it in another cpp file, I am declaring it as extern and this file has multiple functions that use it so I am doing this globally. Now the value of this variable can be accessed in one of the functions and not in the other one. Any suggestions except using it in a header file would be good because I wasted 4 days playing with that.
Sorry, I'm ignoring the request for answers suggesting anything other than the use of header files. This is what headers are for, when you use them correctly... Read carefully:
global.h
#ifndef MY_GLOBALS_H
#define MY_GLOBALS_H
// This is a declaration of your variable, which tells the linker this value
// is found elsewhere. Anyone who wishes to use it must include global.h,
// either directly or indirectly.
extern int myglobalint;
#endif
global.cpp
#include "global.h"
// This is the definition of your variable. It can only happen in one place.
// You must include global.h so that the compiler matches it to the correct
// one, and doesn't implicitly convert it to static.
int myglobalint = 0;
user.cpp
// Anyone who uses the global value must include the appropriate header.
#include "global.h"
void SomeFunction()
{
// Now you can access the variable.
int temp = myglobalint;
}
Now, when you compile and link your project, you must:
Compile each source (.cpp) file into an object file;
Link all object files to create your executable / library / whatever.
Using the syntax I have given above, you should have neither compile nor link errors.

How can I avoid the LNK2005 linker error for variables defined in a header file?

I have 3 cpp files that look like this
#include "Variables.h"
void AppMain() {
//Stuff...
}
They all use the same variables inside them so they have the same headers but I get stuff like this
1>OnTimer.obj : error LNK2005: "int slider" (?slider##3HA) already defined in AppMain.obj
Why is that?
Keep in mind that a #include is roughly like cutting and pasting the included file inside the source file that includes it (this is a rough analogy, but you get the point). That means if you have:
int x; // or "slider" or whatever vars are conflicting
in the header file and that header file is included by three source files in a program, then they will all have a global named x defined that will conflict.
What you want to do is define the variable as extern so that the .cpp files will all get the declaration, and then in ONE of your .cpp files give the actual definition.
in Variables.h:
extern int x;
in SomeSourceFile.cpp
int x;
Of course, I'd recommend against globals, but if you must use them this would keep them from conflicting.
This is because the compiler compiles each .cpp file separately, creating a .obj file for each one. Your header appears to have something like:
int slider;
When this is included into each of your three .cpp file, you get three copies of the int slider variable, just as if you had declared it in each .cpp file. The linker complains about this because you haven't have three different things with the same name.
What you probably want to do is change your header file to read:
extern int slider;
This tells the compiler that there is a slider variable somewhere, but possibly not here, and lets the linker figure it out. Then, in one .cpp file:
int slider;
gives the linker one actual variable to link.
Because "int slider" is already defined in another file? Check that you have header guards...
#ifndef _VARIABLES_H_
#define _VARIABLES_H_
int slider;
#endif
If it is across multiple translation units, and you do want the variables to be different (ie not global), then maybe declare them in an anonymous namespace:
namespace {
int slider;
}
If you do want them global, look to James' solution.
What is happening is that each of the variables from Variables.h are given global scope for each of the individual c files. When the linker compiles all the c files, it sees multiple variables with the same name.
If you are wanting to use variables from the header file as global variables, then you will have to use the keyword "extern" in front of all of them, and in the main file don't use the keyword extern.
main c:
int n_MyVar;
other files:
extern int n_MyVar;
You can create two files Variables.h and EVariables.h, or just declare the variables in the main.cpp file.
A much better way to do this is to create a class of Variables and pass a reference to the class.
I know that this is an old thread, but I came across this as one of the first search results from Google. I solved the problem by placing the variable static.
namespace Vert
{
static int i;
}
I tried extern and in my situation that didn't seem to solve the problem.
This linking error can also be avoided if the variables included multiple times via the "Variables.h" are declared as const.
I had this error too although I work with extern definitions. The problem was initializing the variables in the extern definitions too:
ID3D11VertexShader* g_pVertexShader = nullptr;
...
extern ID3D11VertexShader* g_pVertexShader = nullptr; // here's the problem
=> error
ID3D11VertexShader* g_pVertexShader = nullptr;
...
extern ID3D11VertexShader* g_pVertexShader; // without initializing
=> no error, problem solved

Declaring a global in a global header file?

I have a header file, lets say Common.h, that is included in all of the files over several projects. Basically i want to declare a global variable, e.g.:
class MemoryManager;
DLL_EXPORT MemoryManager* gMemoryManager;
When i do this i get tons of linker errors saying
class MemoryManager* gMemoryManager is already defined.
:(?
As it is you are creating a separate copy of the variable in each compiled file. These are then colliding at the linking stage. Remember that the preprocessor reads in all the header files and makes one big file out of all of them. So each time this big file is compiled, another identical copy of gMemoryManager is created.
You need to use extern and define it in one non-header file.
In your header file
extern DLL_EXPORT MemoryManager* gMemoryManager;
In one of your C++ files
DLL_EXPORT MemoryManager * gMemoryManager;
By the way I have no idea what DLL_EXPORT does, I am just assuming it needs to go in both places.
This
MemoryManager* gMemoryManager;
defines a variable. If you do this in a header, the variable will be defined in each translation unit that includes that header, hence the linker errors. If you want to declare a variable, do it this way:
extern DLL_EXPORT MemoryManager* gMemoryManager;
and put the definition into exactly one cpp file.
When you want to share a global variable among several source files in C++, you need to declare them only in one header file (.h) as
extern typeName variableName;
And also only the corresponding source file (.cpp) should contain the definition
typeName variableName;
The extern keyword is required to distinguish the declaration from the definition.