20

I have this simple test file:

#include "stack.h"

int main()
{
  Stack* stck = init_stack();

  return 0;
}

and stack.h is defined as follows:

#ifndef STACK_H
#define STACK_H

#define EMPTY_STACK -1
typedef struct stack
{
  char ch;
  struct stack* prev;
} Stack;

extern Stack* init_stack();

extern char pop(Stack*);

extern void push(Stack*, char);

#endif

These two files are in the same directory. But when I do gcc .. to build it, I keep getting the error below:

$ ls
stack.c  stack.h  teststack.c
$ gcc -o testit teststack.c 
/tmp/ccdUD3B7.o: In function `main':
teststack.c:(.text+0xe): undefined reference to `init_stack'
collect2: ld returned 1 exit status

Could anyone tell me what I did wrong here?

Thanks,

user1508893
  • 9,223
  • 14
  • 45
  • 57
  • How does it know where the definition of `init_stack` that is has to use is? Though it includes C++, this question will probably help you: http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix – chris Oct 03 '12 at 05:06
  • 6
    Note that `extern Stack *init_stack();` is a quite different declaration from `extern Stack *init_stack(void);`. The first says there is a function but the argument list is not specified (it's not a variable arguments function, but the number and types of the arguments are not specified). The second says the function takes no arguments. Don't use the empty parentheses notation in C. Note that in C++, empty parentheses mean the same as `(void)`. – Jonathan Leffler Oct 03 '12 at 05:12
  • 1
    @JonathanLeffler Oh, wow! I never knew that! I always thought `(void)` is just the fancy way of `()`. Thanks! – user1508893 Oct 03 '12 at 05:40

1 Answers1

26
 gcc -o testit teststack.c stack.c

You need to compile both C source files and link the object files; this does it all in one command.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I thought the `#include "stack.h"` should take care of it? No? – user1508893 Oct 03 '12 at 05:07
  • @user1508893, All including that does is basically paste it in the including file. `stack.c` can't magically work its way in. – chris Oct 03 '12 at 05:08
  • 4
    (a) The `#include "stack.h"` copies the information from `stack.h` into the `teststack.c` file, giving the compiler information about the function — but not giving its definition. (b) No, you don't need to add `stack.h` to the command line. Both the source files will include `stack.h` as the source is preprocessed before the compilation really gets going. – Jonathan Leffler Oct 03 '12 at 05:10
  • @chris: If all `#include` does is to paste the content of the included file into the including file, then it'd be even more unnecessary to include the `stack.c` in the `gcc` because we no longer need it? (the content is already in `teststack.c` ? – user1508893 Oct 03 '12 at 05:11
  • 1
    The implementation of the function `init_stack()` is not in the header `stack.h` (and it should not be there). Presumably, the implementation is in `stack.c`; that needs to be compiled so that the linker gets to see the definition of `init_stack()`. – Jonathan Leffler Oct 03 '12 at 05:13
  • I think it should be clear by now, but C does not have a module system or anything that comes close. `#include`s are a primitive way to accomplish this, but have these gotchas. – Guido Dec 11 '13 at 16:39