can global variables be accessed and modified in various classes in C++ - c++

I have run into code spaghetti where i need to instrument flow control i.e., send data one at a time. How can i use global variable to solve this? If global variables don't work, what is the way to access and modify variables in multiples functions which could be in different classes
I tried the following (I am pasting partial code) but it gave me ld error that I could not resolve. I want to ask what might be the best and clean approach to solve this.
file1.h
int data_received; //global variable
class abc
{
.
.
.
public:
void send_data(..)
.
.
.
};
file1.c
void send_data()
{
while(!end_of_file)
{
read_line;
data_received = 0;
transmit_data(line);
while(data_received == 0)
cout<<"waiting for response before proceeding\n";
}
}
file2.c
//data receive class
void transmit_data()
{
....
....
....
//data sent upstream
data_received = 1;
}
I have searched many posts on stackoverflow but there is no clear answer. Some suggest to use extern variable but no clear example of external variable being modified in more than one class functions.

Please learn more about
Declare vs Define in C and C++.
compile vs link
define global variable
// file1.cpp
int data_received;
extern tell complier that data_received can be found when linker.
// file2.cpp
extern int data_received;
in addition, static can limit my_global_var only to be used in file defining it. example
// file3.cpp
static int my_global_var = 1;
Error will be occured in linker
// file4.cpp
extern int my_global_var;

You need to mark that extern in the header file and then define it once, either in file1.c or file2.c
For example
file1.h
extern int data_received;
file1.c
// initialize it
int data_received = 0;
file2.c
// either do this if the include is logically needed
#include "file1.h"
// or
extern int data_received;
// then use it normally
void foo() {
cout << data_received << endl;
}
Or if this is C++ you can declare that variable as a static variable in the class, define it in the .cpp file and then use it like a normal variable but prefixed with the scope resolution for the class. For example
class Something {
public:
static int data_received = 0;
};
void foo() {
cout << Something::data_received << endl;
}

By having your global variable deined in the header file, you will create a copy of it in any 'c' file which it includes. There far the ld will complain.
You need to declare it as 'extern' in the header file an then define it in a single 'c' file.
file1.h
extern int data_received;
file1.c
#include <file1.h>
int data_received = 0;
file2.c
#include <file1.h>
This way you would only define one copy of it and make it known to all files which include the header file.

Related

How to extern global smart pointers that are assigned within SetUpTestSuite?

I have a couple global pointers defined in a UtTestBase.hpp which are to be used by the files that include it (e.g: UtTest1.cpp).
SetUpTestSuite() is static and thus performs a shared set up for all the tests. I view it as preconfiguration. Doing the way I have would complain about multiple definitions of the globals however using extern for each doesn't work either.
Using extern errors out
namespace TEST
{
extern std::weak_ptr<int> weakPtr;
extern std::shared_ptr<int> sharedInt;
// ...
}
// errors
undefined reference to `weakPtr' in line "weakPtr = sharedInt;"
undefined reference to `sharedInt' in line "sharedInt = std::make_shared<int>();"
From what I have seen the usage of extern involves declaring the variables in a header and defining in a respective source file that uses it
What's the way around? static inline is other option but does it make sense for each file to have a separate instance of a global given they are assigned in SetUpTestSuite()?
UtTestBase.hpp
namespace TEST
{
std::weak_ptr<int> weakPtr;
std::shared_ptr<int> sharedInt;
struct UtTestBase
{
static void SetUpTestSuite()
{
sharedInt = std::make_shared<int>();
weakPtr = sharedInt;
}
// .. some common methods
};
}
UtTestBase.cpp
#include "UtTestBase.hpp"
namespace TEST
{
TEST_F(UtTestBase, Test1)
{
// ...
}
}
UtTest1.cpp
#include "UtTestBase.hpp"
namespace TEST
{
struct UtTest1 : public UtTestBase
{
void SetUp() override
{
// do init for a local test
}
// should have sharedInt and weakPtr assigned
};
}
The reason for the compile error with extern is that this only references the global variable. One of the translation units (exactly one!) has to define it, too. So, in the header, you need it declared with extern, and in one(!) of the cpp files, it additionally needs to be defined without extern.
If you don't define the variable anywhere (and only reference it with extern), the linker will complain that the variable doesn't exist - that's the error messages you're getting.
Here's a simple example with an int.
Header:
//Declare that the variable exists, don't actually create it
extern int g_whatever;
CPP file 1:
#include "Header"
//Create (define) the variable
int g_whatever;
CPP file 2, 3, ...:
#include "Header"
//Use g_whatever, *without* defining it again
This is independent of where you actually initialize the global variable. You could put the definition into UtTestBase.cpp, for example.
For a more in-depth explanation, see: How do I use extern to share variables between source files?

Global const object shared between compilation units

When I declared and initialized a const object.
// ConstClass.h
class ConstClass
{
};
const ConstClass g_Const;
And two cpp files include this header.
// Unit1.cpp
#include "ConstClass.h"
#include "stdio.h"
void PrintInUnit1( )
{
printf( "g_Const in Unit1 is %d.\r\n", &g_Const );
}
and
// Unit2.cpp
#include "ConstClass.h"
#include "stdio.h"
void PrintInUnit2( )
{
printf( "g_Const in Unit2 is %d.\r\n", &g_Const );
}
When i build the solution, there was no link error, what you will get If g_Const is a non-const fundamental type!
And PrintInUnit1() and PrintInUnit2() show that there are two independent "g_Const"s with different address in two compilation units, Why?
==============
I know how to fix it.(use extern keyword to declaration, and define it in one cpp file.)
I wonder to know why I did't get redfined link error in this sample.
https://stackoverflow.com/a/6173889/1508519
const variable at namespace scope has internal linkage. So they're
basically two different variables. There is no redefinition.
3.5/3 [basic.link]:
A name having namespace scope (3.3.5) has internal linkage if it is
the name of
— an object, reference, function or function template that is
explicitly declared static or,
— an object or reference that is explicitly declared const and neither
explicitly declared extern nor previously declared to have external
linkage; or
— a data member of an anonymous union.
Use extern if you want it to have external linkage.
As stated in the other answer, header files are just pasted in cpp files. The same header file is included in both cpp files, but they are separate translation units. That means that one instance of a variable is different from the other instance. In other to let the compiler know that you have defined the variable elsewhere, use the extern keyword. This ensures only one instance is shared across translation units. However extern const Test test is just a declaration. You need a definition. It doesn't matter where you define it as long as it is defined once in some cpp file. You can declare it as many times as you want (which is convenient for placing it in a header file.)
So for example:
Constant.h
class Test
{
};
extern const Test test;
Unit1.cpp
#include "Constant.h"
#include <iostream>
void print_one()
{ std::cout << &test << std::endl; }
Unit2.cpp
#include "Constant.h"
#include <iostream>
void print_two()
{ std::cout << &test << std::endl; }
main.cpp
extern void print_one();
extern void print_two();
int main()
{
print_one();
print_two();
}
Constant.cpp
#include "Constant.h"
const Test test = Test();
Makefile
.PHONY: all
all:
g++ -std=c++11 -o test Constant.cpp Unit1.cpp Unit2.cpp main.cpp
Because you put variable definition in header file. Including header file is just like replacing it with the content of the file. So, the first file:
// Unit1.cpp
#include "ConstClass.h" // this will be replace with the content of ConstClass.h
#include "stdio.h"
void PrintInUnit1( )
{
printf( "g_Const in Unit1 is %d.\r\n", &g_Const );
}
will become (after preprocessing phase before compiling):
// Unit1.cpp
// ConstClass.h
class ConstClass
{
};
const ConstClass g_Const;
//this line is replaced with the content of "stdio.h"
void PrintInUnit1( )
{
printf( "g_Const in Unit1 is %d.\r\n", &g_Const );
}
And the second file will be:
// Unit2.cpp
// ConstClass.h
class ConstClass
{
};
const ConstClass g_Const;
//this line is replaced with the content of "stdio.h"
void PrintInUnit2( )
{
printf( "g_Const in Unit2 is %d.\r\n", &g_Const );
}
As you can see, each file has separate variable g_Const (this is just for the case of your code in here, there maybe no variable at all just like macro, see explanation in my last paragraph).
If what you want is not the definition of the variable just the declaration in the header file, you should use extern keyword in the header file:
extern const ConstClass g_Const;
Then you can put the definition of g_Const variable in ConstClass.c
There is some catch in your code:
there is no constant value assigned in your g_Const definition, you must assign it a constant value in the definition unless you want the default value (0).
inside printf, you take the address of const variable of C++. This actually force the compiler to create the variable in stack. If you don't take the address it may be able to infer a compile time number behaving like macro in C (you can get the magic number directly put in the code where you use the const variable).

Is there any possible use of using extern variable in a file that is not included in any other file?

I've encountered many examples on the web, that have extern int x in main.c, where the main function lies.
The only use of extern I'm aware of, is to make a declaration in another file, and use it in another file, after defining it.
Like :
a.h : extern int x;
a.c : int x = 5;
main.c :
#include "a.h" // and start using x
The 1st case seems redundant to me.
So,
Is there any possible use of using an extern variable in a file that is not included in any other file?
extern tells the compiler that x exists in a different module and should be linked from elsewhere. Putting it in main.c directly just avoids pulling in a header (which would be included in-line anyways)
Just like in a header, x still needs to exist in another .c module where it isn't defined extern.
extern variable has basically two functions one is to use the variable in the other file and the other is to access global variables as in the following code.
int x=10;
int main()
{
int x=20;
cout<<x; //refers to x=20
if(x==20)
{
extern int x;
cout<<x; //refers to the global x that is x=10
}
}
Of course. Using extern in a file lets you use that variable in that file. It doesn't have to be included anywhere else.
The use of extern causes the object to have external linkage; to
instantiate a template with a object (and not a value or a type), the
object has to have external linkage (at least in C++03). Most objects
defined in namespace scope have global linkage, but const objects don't.
So you have something like:
template <char const* n>
class Toto { /* ... */ };
char const n1[] = "abc";
Toto<n1> t1; // Illegal...
extern char const n2[] = "xyz";
Toto<n2> t2; // Legal...
It's sort of a special case, but it has led me (once or twice) to use
extern in an unnamed namespace in a source file.

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

When to use extern in C++

I'm reading "Think in C++" and it just introduced the extern declaration. For example:
extern int x;
extern float y;
I think I understand the meaning (declaration without definition), but I wonder when it proves useful.
Can someone provide an example?
This comes in useful when you have global variables. You declare the existence of global variables in a header, so that each source file that includes the header knows about it, but you only need to “define” it once in one of your source files.
To clarify, using extern int x; tells the compiler that an object of type int called x exists somewhere. It's not the compilers job to know where it exists, it just needs to know the type and name so it knows how to use it. Once all of the source files have been compiled, the linker will resolve all of the references of x to the one definition that it finds in one of the compiled source files. For it to work, the definition of the x variable needs to have what's called “external linkage”, which basically means that it needs to be declared outside of a function (at what's usually called “the file scope”) and without the static keyword.
header:
#ifndef HEADER_H
#define HEADER_H
// any source file that includes this will be able to use "global_x"
extern int global_x;
void print_global_x();
#endif
source 1:
#include "header.h"
// since global_x still needs to be defined somewhere,
// we define it (for example) in this source file
int global_x;
int main()
{
//set global_x here:
global_x = 5;
print_global_x();
}
source 2:
#include <iostream>
#include "header.h"
void print_global_x()
{
//print global_x here:
std::cout << global_x << std::endl;
}
It is useful when you share a variable between a few modules. You define it in one module, and use extern in the others.
For example:
in file1.cpp:
int global_int = 1;
in file2.cpp:
extern int global_int;
//in some function
cout << "global_int = " << global_int;
It's all about the linkage.
The previous answers provided good explanations about extern.
But I want to add an important point.
You ask about extern in C++, not in C and I don't know why there is no answer mentioning the case when extern comes with const in C++.
In C++, a const variable has internal linkage by default (not like C).
So this scenario will lead to linking error:
Source 1 :
const int global = 255; //wrong way to make a definition of global const variable in C++
Source 2 :
extern const int global; //declaration
It needs to be like this:
Source 1 :
extern const int global = 255; //a definition of global const variable in C++
Source 2 :
extern const int global; //declaration
This is useful when you want to have a global variable. You define the global variables in some source file, and declare them extern in a header file so that any file that includes that header file will then see the same global variable.