简体   繁体   中英

head of linked list fails to point to old element

I have this code and I try to create a singly-linked list. However everytime I add a new element at the front, my code fails to point the element at the front of the list to the old element.

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

struct list {
    struct node* head;
};

struct node {
    int data;
    struct node* next;
};

struct list* list_init(void) {
    struct list *l;
    l = malloc(sizeof(struct list));
    if (l == NULL) {
        return 1;
    }
    else {
        l -> head = NULL;
        return l;
    }

}

struct node* new_node(int num) {
    struct node *n;
    n = malloc(sizeof(struct node));
    if (n == NULL) {
        return NULL;
    }
    else {
        n -> data = num;
        n -> next = NULL;
        return n;
    }
}

int list_add_front(struct list* l, struct node* n) {
    if (l == NULL) {
        return 1;
    }
    else {
        if (l -> head == NULL) {
            // Make sure that the list head points to this node.
            l -> head = &n;
        }
        // Make list head point to new node;
        // Make new node point to old head node;
        else {
            struct node* old_head = l -> head;

            n->next = old_head;

            l -> head = &n; 
        }
    }
}

int main()
{
    struct list* l = list_init();
    struct node* nn = new_node(2);

    printf("l address: %p \n", l);
    printf("n address: %p \n", nn);

    list_add_front(l, nn);
    int* datapoint = (l->head)->data;

    printf("List head data at first: %i, on address %p. \n\n", *datapoint, datapoint);

    struct node* nn2 = new_node(12);

    printf("l address: %p \n", l);
    printf("nn2 address: %p \n", nn2);

    list_add_front(l, nn2);
    int* datapoint3 = (l->head) -> data; 
    printf("List head data is now: %i, on address %p. \n\n", *datapoint3, datapoint3);

    struct node* nextnode = (l->head) -> next;
    printf("it points to address %p, which is the list itself. why?? . \n\n", nextnode);



}

I do not know why. It goes wrong in list_add_front I believe. I do not understand how it links to the address of the list struct itself, since printing the pointer seems to give that away.

Here is the executable code online, for convienence maybe: https://onlinegdb.com/rk7_meISN

Thanks in advance all.

As dbush pointed out, you have a number of warnings that need to be fixed. Be sure to compile with -Wall

In particular, in list_add_front , change all &n to n . This should fix the problem. The compiler would/should flag this.

With &n this is a pointer to a pointer of struct node and not a pointer to struct node [which is what you want]. Using &n points to the address of n , which is on the program stack and not what n points to.

Here is an annotated and fixed version. It uses:

#if 0
// original code ..
#else
// fixed code ...
#endif

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

struct list {
    struct node *head;
};

struct node {
    int data;
    struct node *next;
};

struct list *
list_init(void)
{
    struct list *l;

    l = malloc(sizeof(struct list));
    if (l == NULL) {
#if 0
        return 1;
#else
        return l;
#endif
    }
    else {
        l->head = NULL;
        return l;
    }

}

struct node *
new_node(int num)
{
    struct node *n;

    n = malloc(sizeof(struct node));
    if (n == NULL) {
        return NULL;
    }
    else {
        n->data = num;
        n->next = NULL;
        return n;
    }
}

int
list_add_front(struct list *l, struct node *n)
{
    if (l == NULL) {
        return 1;
    }
    else {
        if (l->head == NULL) {
            // Make sure that the list head points to this node.
#if 0
            l->head = &n;
#else
            l->head = n;
#endif
        }

        // Make list head point to new node;
        // Make new node point to old head node;
        else {
            struct node *old_head = l->head;
            n->next = old_head;
#if 0
            l->head = &n;
#else
            l->head = n;
#endif
        }
    }
}

int
main()
{
    struct list *l = list_init();
    struct node *nn = new_node(2);

    printf("l address: %p \n", l);
    printf("n address: %p \n", nn);

    list_add_front(l, nn);
#if 0
    int *datapoint = (l->head)->data;
#else
    int *datapoint = &l->head->data;
#endif

    printf("List head data at first: %i, on address %p. \n\n",
        *datapoint, datapoint);

    struct node *nn2 = new_node(12);

    printf("l address: %p \n", l);
    printf("nn2 address: %p \n", nn2);

    list_add_front(l, nn2);
#if 0
    int *datapoint3 = (l->head)->data;
#else
    int *datapoint3 = &l->head->data;
#endif

    printf("List head data is now: %i, on address %p. \n\n",
        *datapoint3, datapoint3);

#if 0
    struct node *nextnode = (l->head)->next;
#else
    struct node *nextnode = l->head->next;
#endif

    printf("it points to address %p, which is the list itself. why?? . \n\n",
        nextnode);

#if 1
    return 0;
#endif
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM