views:

118

answers:

7

Hi, I'm a newbie to programming in C, and I'm having trouble understanding the error that is coming up when I attempt to compile my program. I've got the following program, which is fairly simple and which my professor says is correct:

#include <stdio.h>
#define TRUE 1
#define FALSE 0
#define BOOL int

extern int x;
extern BOOL do_exp;
int exp_or_log();

main()
{
   x = 10;
   do_exp = TRUE;
   printf("2^%d = %d\n", x, exp_or_log());  //should print 1024

   x = 145;
   do_exp = FALSE;
   printf("log(%d) = %d\n", x, exp_or_log());  //should print 7
}

But when I try to compile it, I get:

  "_x", referenced from:
      _x$non_lazy_ptr in ccWdLlxk.o
  "_exp_or_log", referenced from:
      _main in ccWdLlxk.o
      _main in ccWdLlxk.o
  "_do_exp", referenced from:
      _do_exp$non_lazy_ptr in ccWdLlxk.o
ld: symbol(s) not found

I don't even have enough of an idea of what that means to know where to begin trying to figure out the problem. If anyone has a helpful explanation, or even just a general idea of what I should look at to begin problem shooting, I'd really appreciate it.

+1  A: 

what about the data type int inside main()

http://tigcc.ticalc.org/doc/keywords.html#extern

zod
+1  A: 

It's not the compiler that is complaining:

ld: symbol(s) not found

The linker (ld) cannot find the referenced symbols. You haven't provided their definitions.

pmg
+1  A: 

You've declared to the compiler that these variables and functions are available, but not necessarily defined in this particular source file:

extern int x;
extern BOOL do_exp;
int exp_or_log();

And they are not defined in that source file. However, the linker needs to be able to resolve those names, and the error message you're getting indicates that the linker can't find those names in any of its input files.

You need to wither provide the linker (ld) with a library that has these things, or you need a C file that defines them, and ahave that C file also compiled and linked in.

Michael Burr
+2  A: 

x, do_exp, and exp_or_log() are all defined in another file, I'm guessing supplied by your professor. You need to link together with that file. This is usually done by adding its filename along with yours on your compile line.

Karl Bielefeldt
A: 

You're having linker problems.

See the top of your code:

extern int x;
extern BOOL do_exp;
int exp_or_log();

Those three lines are like promises to the compiler. You're saying, trust me, when the time comes you'll be able to find an integer x, a BOOL do_exp, and a function exp_or_log();

The extern makes this promise for variables and the fact that the function doesn't have a body: {...} makes it for the function.

The linker is complaining because you're not following through on your promise. You need an implementation of exp_or_log(), and to have declared x and do_exp.

Is there more code? If you make another file, call is x.h, with the following content: int x; int do_exp; int exp_or_log() { return 6; }

and then include this in your .c file:

#include "x.h"

You'll get some output. In this case it's nonsensical but it will compile while you fix the logic problems.

$ ./a.out
2^10 = 6
log(145) = 6
Paul Rubel
+1  A: 

First, note how you used the extern keyword on two variable definitions.

extern int x;
extern BOOL do_exp;

This means:

These variable are created elsewhere (extern ally). You should be aware that they exist, but they exist somewhere else.

If these variable are intentionally declared in another file, you need to link compile that other file with yours, and link them together.

However, I suspect it is more likely that you just meant to declare them.

int x;
BOOL do_exp;

Report back on this, then we'll begin dealing with your function exp_or_log.

abelenky
+1  A: 

I'm guessing you're using a *nix machine from the output, so you would need to:

cc -c Anna_program.c

This should produce Anna_program.o. In your error the gibberish .o file was the same as this one, but was temporary, so was given a psudo-random name. The -c flag has the effect of only compiling the source file, and leaves off linking, which produces the executable, for later.

Then you can do:

cc Anna_program.o other_file.o -o Anna_program

And produce the executable Anna_program. If you aren't using a *nix style compiler then your sets will be different and you may need to put an extension on the end of the output file name in the last command.

You could do:

cc Anna_program.c other_file.o -o Anna_program

Which would combine the previous two steps.

What you should remember is that cc (or gcc) aren't actually the compiler, but a simple compilation manager. Under the hood they run other programs which do different steps in building your programs. By default cc will try to take what you give it and produce an executable (a.out), running as many of the steps as needed based on what you have given it. You can pass it flags, such as -c to tell it to only go part way (compiling and assembling, in this case).

The steps for C are Preprocessing (done by the program cpp), compiling (done by cc1), assembling (done by as), and linking (done by ld).

The cc or gcc command decides what needs to be done and then runs these other programs to do it.

nategoose