0

I'm working through exercises from Programming Principles and Practice using Visual Studio 2012. When trying to compile the source code below I'm getting a linker error:

unresolved symbol int foo.

I don't understand why the symbol is unresolved.

my.h

extern int foo;
void print_foo();
void print(int);

my.cpp

#include "my.h"
#include "../../std_lib_facilities.h"

void print_foo()
{
    cout<<foo<<'\n';
}

void print(int i)
{
    cout<<i<<'\n';
}

use.cpp

#include "my.h"

int main(){
    int foo = 7;

    print_foo();
    print(99);
}
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
dcrearer
  • 1,972
  • 4
  • 24
  • 48
  • 2
    Format your code properly please! – πάντα ῥεῖ Jul 02 '14 at 22:29
  • 10
    You never defined a `foo` in the global namespace. `extern int foo;` is only a declaration, not a definition. The only definition of `foo` is a local variable in `main()`. – T.C. Jul 02 '14 at 22:30
  • does it matter which of the files the global definition for foo is? – dcrearer Jul 02 '14 at 22:36
  • Yes, and No. No; you could define it in either source file (not the header) and the code would link. Yes; you should define it in `my.cpp` because it is part of the interface provided by the `my.h` and `my.cpp` files. If you have 6 programs using the `my` package, you'd not want the each of those programs to have to define the global `foo`. – Jonathan Leffler Jul 02 '14 at 22:39
  • T.C. thanks a lot the info provided was very helpful. – dcrearer Jul 02 '14 at 22:46

2 Answers2

5
extern int foo;

This is a declaration. It tells the compiler "there's going to be an variable called foo of type int in the global namespace defined somewhere".

int main(){    
    int foo = 7;
    // ...
}

This defines a local variable foo of type int inside the function main() and initializes it to 7. This local variable is not visible outside of main().

What you didn't do is actually define foo in the global namespace. To do that, add this line to exactly one of either my.cpp or use.cpp, after the includes:

int foo;

This defines a variable called foo of type int in the global namespace. (As an object of static storage duration, foo is initialized to zero by default, though you can also provide a different initializer if you want.) The linker should then be able to resolve the reference to the global foo that's in print_foo() when you link the object files together.

It is very important that you only define foo once, though you can declare it as many times as you want. Doing otherwise violates the One Definition Rule and results in a linker error if you are lucky, and undefined behavior if you are not.

T.C.
  • 133,968
  • 17
  • 288
  • 421
2

This statement

extern int foo;

is a declaration of name foo. It is not the definition of foo.

You have to initialize this variable that it would be a definition. For example

extern int foo = 0;

Though I do not see a sense in your code.

Maybe you meant the following. I suppose that the variable defined in the module because I do not see a sense of using the header if there is only one module.

/* my.cpp */

#include "../../std_lib_facilities.h"

extern int foo = 0;
void print_foo();
void print(int);

void print_foo()
{
    cout<<foo<<'\n';
}

void print(int i)
{
    cout<<i<<'\n';
}

int main(){

    extern int foo;
    foo = 7;

    //...

If you want to use header then the code could look as

/* my.h */

extern int foo;
void print_foo();
void print(int);

/* my.cpp */

#include "my.h"
#include "../../std_lib_facilities.h"


int foo;

void print_foo()
{
    cout<<foo<<'\n';
}

void print(int i)
{
    cout<<i<<'\n';
}

/* use.cpp */

#include "my.h"

int main(){

    extern int foo;
    foo = 7;

    print_foo();
    print(99);
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 2
    You don't have to initialize a variable to make it a definition. `extern` means 'defined elsewhere'. A definition would be just `int foo;`. – nullptr Jul 02 '14 at 22:39
  • 1
    And anyway, putting the definition for non-inline functions or for variable into headers is a bad idea. – Deduplicator Jul 02 '14 at 22:40
  • There are several ways to define the variable. One is the technique shown by Vlad (`extern int foo = 0;`); another is to omit the `extern`, leaving `int foo = 0;`, while yet a third would omit both `extern` and the initializer (`int foo;` at file scope). Of course, the variable definition must not be in the header because if it is put in the header, only one file per program can include the header, which makes the header pointless in the first place. – Jonathan Leffler Jul 02 '14 at 22:41
  • @Inspired You said a stupidy. The linker issued the error that the variable is undefined. So you have to define it. – Vlad from Moscow Jul 02 '14 at 22:43
  • `extern int foo;` is needless in `main()'. Header file `my.h` provides info about global variable `foo`. – Dakorn Jul 02 '14 at 22:59
  • @Dakorn I provided two code examples. The both code examples are correct. What code example are you speaking about? – Vlad from Moscow Jul 02 '14 at 23:04