Implicit declaration of function in doubly linked list using C

176 views Asked by At

This isn't the final implementation of the program, but the program itself was a bit long so I decided to create it in small chunks instead. I'm running into an error that says

implicit declaration of function list_first.

There are other errors to tackle, but I would like to get some help with this first and then work on the rest myself, although you are welcome to give out extra help if you feel like it. Here's the code:

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

// The type for a node in the list.
struct node
{
    struct node *next;
    struct node *prev;
    char *value;
};

// The type for a list.
typedef struct list
{
    struct node head;
} List;

// The type for a list position.
typedef struct list_pos
{
    struct node *node;
} ListPos;

List *list_create(void)
{
  List *lst = (List*)malloc(sizeof(List));
  if(lst == NULL)
  {
    printf("No more memory!\n");
  }

  return lst;
}

static struct node *make_node(const char *value)
{
  struct node *result = malloc(sizeof(struct node));
  result->value = strdup(value);
  result -> next = NULL;
  result -> prev = NULL;
  return result;
}
static void add_values(List *lst)
{
    ListPos pos = list_first(lst);
    pos = list_insert(pos, "Apple");
    pos = list_next(pos);
    pos = list_insert(pos, "Banana");
    pos = list_next(pos);
    pos = list_insert(pos, "Citrus");
}

ListPos list_end(List *lst)
{
    ListPos pos = {
        .node = &lst->head
    };
    return pos;
}

ListPos list_first(List *lst)
{
    ListPos pos = {
        .node = lst->head.next
    };
    return pos;
}
ListPos list_next(ListPos pos)
{
  struct node* node;

  //pos = node -> next;
  struct node *before = pos.node->prev;
  struct node *after = pos.node;

   node->next = after;
   after->prev = node;

  pos.node = node;
    return pos;
}
ListPos list_insert(ListPos pos, const char *value)
{
    // Create a new node.
    struct node *node = make_node(value);

    // Find nodes before and after (may be the same node: the head of the list).
    struct node *before = pos.node->prev;
    struct node *after = pos.node;

    // Link to node after.
    node->next = after;
    after->prev = node;

    // Link to node before.
    node->prev = before;
    before->next = node;

    // Return the position of the new element.
    pos.node = node;
    return pos;
}


int main(void)
{

    // Create an empty list.

      List *lst = list_create();
      add_values(lst);
    return 0;
}
3

There are 3 answers

0
Vlad from Moscow On BEST ANSWER

In the function add_values

static void add_values(List *lst)
{
    ListPos pos = list_first(lst);
    //..

there is called the function list_first that was not yet declared.

You need to place a declaration of the function list_first before its usage in the function add_values.

For example

ListPos list_first(List *lst);

static void add_values(List *lst)
{
    ListPos pos = list_first(lst);
    //..

Pay attention to that this declaration

typedef struct list
{
    struct node head;
} List;

does not make a great sense. You should use the following declaration of the list

typedef struct list
{
    struct node *head;
    struct node *tail;
} List;

The function list_create does not initialize the data member of the dynamically allocated object.

So other functions as for example list_first invoke undefined behavior accessing the uninitialized data member head as in this declaration

ListPos pos = {
    .node = lst->head.next
};
2
CTZ On

It must be the prototype of the function or the function definition itself before the line in which the function is used. Add prototype definitions after typedef declarations for the function and other functions you specify.

2
Luis Colorado On

implicit declaration of function list_first.

This means the compiler has seen a function call called list_first, but you (or the include files you use in the compilation unit) have not provided the interface to that function (the type returned by it, or the list and types of the arguments passed to it) In old C, this was permitted, assuming by default (which can be probably too dare) the function returns an int value and takes an undefined list of parameters, as defined by this prototype (which probably is not the correct one):

int list_first();

So you probably need to provide a correct definition for that function in a header file (if the function was written by you) and #include it in your source file, or just #include the file in which a definition for the function is given.

Old versions of the standard allowed this, with the default behaviour shown above in the compiler, but recent versions of the standard forbid it (well, if you wrote the function, why don't include a header file that tells the compiler how to use it? or if you didn't, why let the compiler guess and don't provide a correct interface?)