- If you will think back with me to our first slide, we had a program
split into two source code files, main.c and stuff.c.
Let's say that main.c calls a routine int doStuff(int,int).
doStuff is defined in stuff.c, but everytime we compiile
main.c we get an error because main.c can't see that
definition.
- We have already seen the solution to this problem, of course. By
including a function declaration (or prototype) with an
extern in front, we tell the compiler that the function will be
included at link time. The extern keyword is actually optional,
so both
extern int doStuff(int,int);
and
int doStuff(int,int);
are allowable.
- We could do the same thing with a global variable stuffStatus
that is defined in stuff.c but that we want main.c to see.
Just put the line
extern int stuffStatus;
at the top of the main.c.
Of course, in this case, the extern is no longer optional: if we
had
int stuffStatus;
then the compiler would think we were defining a new int variable.
- All functions and all extern global variables have external
linkage; that is, other functions in other files can use them and link
to them. If you want a function to have internal linkage, if you
don't want any functions in any other file to use it, you can proceed it with
the static keyword. If, for example, doStuff was defined
in stuff.c as
static int doStuff(int a, int b)
{ ... }
then when we linked main.c and stuff.c together, the linker
would complain that it couldn't find ("unresolved symbol") doStuff.
- One way to think about all of this is to consider what names (symbols)
get put into the object code files. Only non-static function names
and extern global variable names get put into the .o files
after compilation. These, then, are the only symbols the linker knows about.
To find out what symbols a .o or .a (library) file contains,
use the UNIX nm program:
# nm event.o
00000000 T addevent
00000000 t gcc2_compiled.
00000010 T nextevent