cstructcompiler-errorsfunction-declarationimplicit-declaration

Implicit declaration of function in doubly linked list using C


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;
}

Solution

  • 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
    };