I want to implement a source file that contains a global variable, and I want to do this through inline static
. I can change a variable (e.g., i
) within the context of a translation unit, but when I call the variable outside of that translation unit, the result will remain unchanged for the caller. It's like there is a copy for each unit. See the below example:
header.h
#ifndef UNTITLED1_TEST_H
#define UNTITLED1_TEST_H
namespace t {
inline static int i{0};
void inc() ;
void print_i() ;
}
#endif //UNTITLED1_TEST_H
header.cpp
#include "header.h"
void t::inc() {
t::i ;
}
void t::print_i() {
std::cout << t::i << std::endl;
}
So let's see how the program performs:
main.cpp
#include "header.h"
int main() {
t::inc();
std::cout << t::i << std::endl; // -> output is: 0
t::print_i(); // -> output is : 1
}
As you can see, the variable i
has different values across different translation units, how can this be resolved? I cannot use classes or anything else since the client wants the code in this format.
note
I can do such things as below, but it isn't the main issue, I want a global variable:
t::i ; //instead of t::inc();
std::cout << t::i << std::endl; // it's okay now, but it's not what I wanted
Alternatively, I can use inline
instead of inline static
. It seems to be working, but my mentor said that I should use inline static
instead.
CodePudding user response:
static
variables (as in your example) have internal linkage. There are 2 ways to achieve what you want, both of which are shown below. Also note that the static
keyword has other meanings as well.
Method 1: C 17
With C 17, we can use the inline
keyword as shown below:
header.h
#ifndef UNTITLED1_TEST_H
#define UNTITLED1_TEST_H
namespace t {
inline int i{0};//note the keyword inline here and initializer while keyword static has been removed
void inc() ;
void print_i() ;
}
#endif
header.cpp
#include "header.h"
#include <iostream>
//No need for initilaizing t::i here
void t::inc() {
t::i ;
}
void t::print_i() {
std::cout << t::i << std::endl;
}
main.cpp
#include <iostream>
#include"header.h"
int main() {
t::inc();
std::cout << t::i << std::endl; // -> output is: 1
t::print_i(); // -> output is : 1
}
The output of method 1 can be seen here.
Method 2: Pre-C 17
Here we make use of the extern
keyword so that the variable can have external linkage.
main.cpp
#include <iostream>
#include"header.h"
int main() {
t::inc();
std::cout << t::i << std::endl; // -> output is: 1
t::print_i(); // -> output is : 1
}
header.h
#ifndef UNTITLED1_TEST_H
#define UNTITLED1_TEST_H
namespace t {
extern int i;//note the keyword extern and no initializer here
void inc() ;
void print_i() ;
}
#endif
Note I have removed added the static
and inline
keywords, and added the extern
keyword. Now the variable has external linkage. Also, note that the initialization of t::i
is done in header.cpp given below.
header.cpp
#include "header.h"
#include <iostream>
int t::i{}; //initialize t::i
void t::inc() {
t::i ;
}
void t::print_i() {
std::cout << t::i << std::endl;
}
Output of the above program is: Demo
1
1
Also, do note that the keyword static
has other meanings as well. But I have answered according to the given example code snippet.
CodePudding user response:
There are many different meanings of the keyword static
, depending on context. You are using static
in a wrong context. You can do this
namespace t {
inline int i{0}; // no static
}
or this
class t {
public:
inline static int i{0};
}:
All of this should be in a header file, with no other definition in a .cpp file and no extern
keyword. These things are required in C 14 or earlier, but not in C -17 or later.