undefined reference to `stack_init'

Viewed 179

test.c

#include <stdio.h>
#include <stdlib.h>
#include "dslib.h"
//#include "stack.c"

int main()
{
    stack myStack;
    char buffer[1024];

    stack_init(&myStack, 6);
    int i;

    for(i = 0; i < myStack.max; i++){
      stack_push(&myStack, (i+1)*2);
    }
    printf("Hello\n");
    return 0;

stack.c

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "dslib.h"
//#define stack_init main

void stack_init(stack *s, int capacity)
{
  //  struct stack_t *s = (struct stack_t*)malloc(sizeof(struct stack_t));

    s->max = capacity;
    s->count = -1;
    s->data = (int*)malloc(capacity * sizeof(int));
    //return s;
}

int stack_size(stack *s)
{
    return s->count;
}

int stack_pop(stack *s)
{
    if(s->count == 0){
      return -1;
    }
    s->count--;

    int pop = s->data[s->count];
    s->data[s->count] = 0;
    return pop;
}

void stack_push(stack *s, int e)
{
    if(s->count != s->max){
      s->data[s->count] = e;
      s->count++;
    }
}

void stack_deallocate(stack *s)
{
  free(s->data);
}

dslib.h

#ifndef DSLIB_H
#define DSLIB_H

#include <stdio.h>
#include <stdlib.h>

typedef struct stack
{
int count; // the number of integer values currently stored in the stack
int *data; // this pointer will be initialized inside stack_init(). Also, the actual size of
//the allocated memory will be determined by “capacity’ value that is given as one of the
//parameters to stack_init()
int max; // the total number of integer values that can be stored in this stack
}stack;

void stack_init(stack* s, int capacity);
int stack_size(stack *s);
int stack_pop(stack *s);
void stack_push(stack *s, int e);
void stack_deallocate(stack *s);

#endif

Makefile

cc=gcc

file: test.o stack.o file.o
    gcc -o file test.o stack.o file.o

file.o: file.c
    gcc -o file.o file.c

test.o: test.c
    gcc -o test.o test.c

stack.o: stack.c
    gcc -o stack.o stack.c

When I execute make, it emits this:

gcc -o test.o test.c
/tmp/ccJMitGw.o: In function `main':
test.c:(.text+0x2a): undefined reference to `stack_init'
test.c:(.text+0x53): undefined reference to `stack_push'
collect2: error: ld returned 1 exit status
Makefile:10: recipe for target 'test.o' failed
make: *** [test.o] Error 1
3 Answers
gcc -o test.o test.c

This attempts to compile and link test.c into an executable with the unusual name of test.o. That obviously fails because test.c is not a complete program by itself.

To just compile and assemble a source file into an object file, you need to use the -c option:

gcc -c -o test.o test.c

And the same for the other compilation rules of your makefile.

There is a slight inconsistency in gcc's behavior here: it looks at the extension of the input files to help it decide what to do (.c files get compiled as C, .cpp files are compiled as C++, .s files are only assembled, etc) but it doesn't look at the extension of the output file. You have to use a separate option.

My answer is intended to follow on Nate's. Mine's a bit too complicated to put into a comment.

The default file production rules should work just fine for your Makefile unless on your platform the defaults are different. On mine, this is all I need to make the executable:

file: test.o stack.o
    gcc -o file test.o stack.o

You didn't include file.c but the code you posted doesn't depend upon file.c.

It's highly recommended to use pre-defined rules whenever possible and to define new rules where they can be applied more than once. The only time you truly need specific rules is when multiple rules cannot be refactored to a smaller set of rules.

PS I'd never want to create an executable named for something that already exists.

Create a header file for the stack.c file and include it in your main file instead of stack.c

stack.h

#ifndef STACK_H
#define STACK_H

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "dslib.h"

void stack_init (stack * s, int capacity);

int stack_size (stack * s);

int stack_pop (stack * s);

void stack_push (stack * s, int e);

void stack_deallocate (stack * s);

#endif

stack.c

#include "stack.h"

/* code */

test.c

#include "stack.h"

/* code */
Related