链表头无法指向旧元素

head of linked list fails to point to 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);



}

不知道为什么。我相信 list_add_front 它出错了。 我不明白它是如何链接到列表结构本身的地址的,因为打印指针似乎泄露了它。

这里是网上的可执行代码,为了方便起见可能是:https://onlinegdb.com/rk7_meISN

在此先感谢大家。

正如 dbush 指出的那样,您有许多警告需要修复。一定要用-Wall

编译

特别是,在list_add_front中,将所有&n更改为n。这应该可以解决问题。编译器 would/should 对此进行标记。

对于&n,这是指向struct node的指针,不是指向struct node的指针[这就是你想要的].使用&n指向n地址,它在程序栈上不是什么n 指向.

这是一个带注释的修复版本。它使用:

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