views:

171

answers:

6

I have got 2 cpp files & a header file, which I have included in both cpp files. It's like this:

abc.h

extern uint32_t key;

a.cpp

#include "abc.h"
uint32_t key;
int main
{
.............
}

b.cpp

#include "abc.h"

int main
{
printf("Key: %.8x\n", key);
.............
}

Now when I compile a.cpp, there is no error. but when i compile b.cpp it gives error "undefined reference to `key'". Please help me in finding the problem in this code.

+4  A: 

To share a variable, you normally have something like this:

// A.h
extern int key;
void show();

//a.cpp
#include "a.h"

int main() { 
    key = 1;
    show();
};

// b.cpp
#include "a.h"
#include <iostream>

int key;

void show() { std::cout << "Key = " << key; }

There are a couple of points to not here. First of all, you put the extern declaration in a header, and include it in all the files that use the variable. Define the variable (without the extern) in one and only one file. Only one file should contain a function named main.

Edit: to build this, you compile each file by itself, but you have to link the two files together. For example, using gcc you could do something like:

gcc -c a.c
gcc -c b.c
gcc a.o b.o

The first compiles (but does not link) a.c. The second does the same with b.c The third actually links the two together and produces a binary image you can execute (traditionally named a.out, though, for example, on Windows this is normally changed to a.exe).

Jerry Coffin
How is that different from the OP scenario? You defined key in b.cpp, he did it in a.cpp... what was wrong with his way of doing it?
Bruno Brant
This is building a single program from two source files; it looks the OP is trying to build two programs.
Mike Seymour
@Mike: Yeah, I missed the fact that there are two mains. We need to teach the OP about compilation...
Bruno Brant
@Bruno: as it was originally posted, he showed the header being included only in one of the two source files.
Jerry Coffin
+1  A: 

I am guessing you are getting a link error? You need to include a.o when linking b, though if you really have "main" in both a and b that won't work. You will need to make c.cpp which declares key, and link c.o into both a.exe and b.exe.

Zanson
+3  A: 

The problem is exactly what the error message says. Abc.h declares the variable, but it doesn't define it. The line in a.cpp defines it. That is, a.cpp is where the physical storage of the variable appears. There is no such line in b.cpp, so when you try compiling that program, the linker is left without any storage defined for that variable.

If you had omitted the "extern" specifier in the header, then b.cpp would have compiled fine, but a.cpp would likely have given an error about multiple definitions.

The "extern" specifier plays a larger role when you have multiple source files in a single program. In that case, they would probably all include abc.h, but without "extern," each compiled object files would have its own independent definition of the same variable. The linker generally won't know what to do with that, and will probably complain, although I don't think it's required to do so. The fix is to use "extern" so each compiled file file only has a declaration. Then you pick one source file to place the definition in. You'd probably put it in abc.cpp since the declaration is in abc.h.

Rob Kennedy
+2  A: 

You are compiling two separate programs. One cannot reference a variable from the other. The extern keyword is for referencing a symbol from one object file in another object file of the same executable being linked.

Nikolai N Fetissov
+1  A: 

The line from the header file is a declaration; it tells the compiler that the variable exists, but doesn't allocate any space for it. When you build a program from one or more source files, one of them must also contain a definition.

In your case, you have a definition in a.cpp, so that contains everything needed to build the program. b.cpp has no definition, so it will fail to link.

There are two solutions. Either copy the definition from a.cpp to b.cpp, or move it to a third source file and include that in the list of sources when building both programs.

Mike Seymour
A: 

Both a.cpp and b.cpp have main() functions defined, and you're only allowed to define one main() per program. So, I assume what you're trying to do is share a header file between two programs. In that case, add the line to b.cpp to define key and recompile:

uint32_t key;

This isn't the normal way to use header files. Instead you write your functions to take key as a parameter. Doing it this way sets up a global variable, which is generally frowned on.

extern is almost always used to set up a global variable (off the top of my head, I can't think of any other reason to use extern). But if you want to use extern the way it's normally used -- without going into whether it should be used at all -- you would do the following:

  • remove the main() function from one of the two files, for the purposes of this answer we'll remove it from b.cpp.
  • Use the following two lines to compile and link your program (assuming gcc):

    gcc -c -o b.o b.cpp

    gcc a.cpp b.o

The -c option to gcc (first line) says "compile only, do not link." It's the linking step that determines if all variables are defined, and they aren't defined when you compile b.cpp, but they are defined when you compile a.cpp (second line).

Max Lybbert