Home > Back-end >  inline static variable in different translation units has different values(c 17)
inline static variable in different translation units has different values(c 17)

Time:02-19

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.

  • Related