1

I have this simple program which tries to print my global variable in a separate file. I'm using the Visual Studio 2013 professional IDE.

print.h

#ifndef PRINT_H_
#define PRINT_H_

void Print();

#endif

print.cpp

#include "print.h"

#include <iostream>

void Print()
{
    std::cout << g_x << '\n';
}

source.cpp

#include <iostream>
#include <limits>

#include "print.h"

extern int g_x = 5;

int main()
{
    Print();

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cin.get();

    return 0;
}

I get a compiler error error C2065: 'g_x' : undeclared identifier.

I've searched through this forum and was unable to find anyone else having my problem. I've tried re-declaring my global variable in the separate .cpp file with no success. As you can see, I've included the necessary header guards and assigned my global variable the extern keyword. This is my first time testing global variables in multiple files. Obviously I'm missing something simple. What do I need to change or add to make my program work?

EDIT: I found this topic useful in understanding the difference between extern and the definition of a global variable.

Community
  • 1
  • 1
Wandering Fool
  • 2,170
  • 3
  • 18
  • 48
  • You might want to look at [this](http://stackoverflow.com/questions/10422034/when-to-use-extern-in-c) – jaggedSpire May 28 '15 at 18:53
  • @jaggedSpire I read your link but I'm still unsure what I need to change in my program. I have `extern` and when I redefine my global variable in `print.cpp` it still won't compile. – Wandering Fool May 28 '15 at 19:00
  • You shouldn't be defining the variable in the header file, just declaring it to be defined elsewhere, and then including the declaration in the relevant .cpp files. – jaggedSpire May 28 '15 at 19:04

3 Answers3

4

The compiler is compiling print.cpp. It knows nothing about source.cpp while it is compiling print.cpp. Therefore that g_x that you placed in source.cpp does you absolutely no good when print.cpp is being compiled, that's why you get the error.

What you probably want to do is

1) place extern int g_x; inside of print.h. Then the compiler will see g_x when compiling print.cpp.

2) in source.cpp, remove the extern from the declaration of g_x:

int g_x = 5;
PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
3

Move your global declaration to a common header, like common.h:

#ifndef COMMON_H_
#define COMMON_H_

extern int g_x;   //tells the compiler that g_x exists somewhere

#endif

print.cpp:

#include <iostream>

#include "print.h"
#include "common.h"

void Print()
{
    std::cout << g_x << '\n';
}

source.cpp:

#include <iostream>
#include <limits>

#include "print.h"
#include "common.h"

int g_x;

int main()
{
    g_x = 5;   //initialize global var
    Print();

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cin.get();

    return 0;
}

In other .cpp files, you can access g_x including the common.h header.

JosEduSol
  • 5,268
  • 3
  • 23
  • 31
  • Why did you move the initialisation into `main`? – Lightness Races in Orbit May 28 '15 at 19:05
  • @JosEduSol I was wondering the same thing? If you initialize it in `main()`, doesn't that *name hide* or *shadow* the global variable? – Wandering Fool May 28 '15 at 19:07
  • @Wandering I suspect that it doesn't hide it since you're not declaring the variable there. However, you do not need to do so. Simply defining it within a .cpp file in the global scope should work quite well. – jaggedSpire May 28 '15 at 19:10
  • @jaggedSpire Am I right to assume that I do not need to initialize this more than once if I had more .cpp files I want to use it in? – Wandering Fool May 28 '15 at 19:13
  • @Wandering that has not been my experience. And a brief experiment says no, as well. – jaggedSpire May 28 '15 at 19:13
  • The var need to be defined in only one of the files that included common.h. At first i had an error by redefinition, so i moved initialization somewhere. – JosEduSol May 28 '15 at 19:15
  • @JosEduSol So does that mean the global variable needs to be declared as an extern before you initialize it? In other words, the common.h file is required in my source.cpp file where I'm initializing my global variable? – Wandering Fool May 28 '15 at 19:17
  • @WanderingIdiot `extern int g_x;` is a _declaration_, and `int g_x;` is a _definition_. The general idea is to _define_ the global var once somewhere and _declare_ it `extern` in other modules where you want to use it. Definitions must be done exactly once, otherwise linker will complain. – JosEduSol May 28 '15 at 19:49
  • @JosEduSol What really made me understand this is that `extern int g_x;` is specifically a forward declaration. That means when you put `extern` in a header file, you're actually copying a forward declaration into each .cpp file that includes it. This means that jaddedSpire was wrong in assuming that my source.cpp file needed to include the common.h. Since a definition such as `int g_x = 5;` which is already in my source file does not need a declaration when the definition itself will suffice. This also means that your inclusion of the common.h in source.cpp above is redundant. – Wandering Fool May 28 '15 at 20:36
  • If my comment came off as a little rough that wasn't my intention. I'm just sharing what I understand. – Wandering Fool May 28 '15 at 20:36
  • @WanderingIdiot Nahh, its ok. But, the word redundant is not the more appropriate here. Let me explain, i just give you an approach where you could put all your global vars in a header called common.h. But because in this case you have only one global var, you look at this solution as over complicated/redundant/unnecessary or whatever. And i agree with you that the accepted solution is the best for your case, but i just went for this way. – JosEduSol May 28 '15 at 22:44
  • What about if you had g_x, g_x2, g_x3, g_x4, and so up to g_xN?, you need to declare `extern int g_x`, `extern int g_x2`, `extern int g_x3` and so on in every module where you want to share the global vars?. Maybe in this case you prefer just to include one header file and thats all. Or maybe a better more C++like way of doing it would be declaring static vars into a class. – JosEduSol May 28 '15 at 22:47
  • That makes sense. If you have a bunch of globals in one header then you might want to include it anyways even if you're not going to be using all of them. – Wandering Fool May 28 '15 at 23:12
0
extern int g_x;

belongs to .h, and you need to add

int g_x =5; 

to some of .cpp.

Ken Y-N
  • 14,644
  • 21
  • 71
  • 114
No-Bugs Hare
  • 1,557
  • 14
  • 15