1

对于下面的链表声明,

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

typedef struct list
{
   int val;
   struct list *next;
} list;


void destroy (list *l)
{
    if (l)
    {
        destroy (l->next);
        free (l);
    }
}

为什么以下主要工作

int main()
{
    list *test;
    list *ptr1, *ptr2;
    int i;
    test = malloc (sizeof (list));
    test->val = 0;
    ptr2 = test;
    for (i = 1; i <= 10; i++)
    {
        ptr1 = (list *) malloc (sizeof (list));
        ptr1->val = i;
        ptr2->next = ptr1;
        ptr2 = ptr1;
    }
    ptr1 = test;
    while (ptr1)
    {
        printf ("%d\n", ptr1->val);
        ptr1 = ptr1->next ;
    }
    destroy (test);
    return 0;
}

而这个甚至没有创建一个列表(它只创建一个节点)?

int main()
{
    list *test;
    list *ptr;
    int i;
    test = malloc (sizeof (list));
    test->val = 0;
    ptr = test->next;
    for (i = 1; i <= 10; i++)
    {
        ptr = (list *) malloc (sizeof (list));
        ptr->val = i;
        ptr = ptr->next;
    }
    ptr = test;
    while (ptr)
    {
        printf ("%d\n", ptr->val);
        ptr = ptr->next ;
    }
    destroy (test);
    return 0;
}

他们不使用相同的逻辑吗?

4

3 回答 3

3

编码

ptr = test->next;
for (i = 1; i <= 10; i++)
{
    ptr = (list *) malloc (sizeof (list));
    ptr->val = i;
    ptr = ptr->next;
}

从获取副本开始,test->next但从不将任何内容分配给test->next自身。因此,从 开始的列表test只有一个项目。更糟糕的是,该项目有一个未初始化的next指针,因此尝试迭代列表的代码几乎肯定会崩溃。

正如其他答案中所暗示的那样,对于每个新分配的节点都会重复此模式。

在回答您的评论时,使第二个功能工作的最佳方法是使其更像第一个(工作)版本。我已重命名其中的变量以使其更清晰

list *head;
list *next, *curr;
int i;
head = malloc (sizeof(*head));
head->val = 0;
curr= head;
for (i = 1; i <= 10; i++)
{
    next = malloc (sizeof(*next));
    next->val = i;
    curr->next = next;
    curr= next;
}
curr= head;
于 2013-06-03T12:53:03.663 回答
1

在第二个主要期间

ptr = test->next;

您正在尝试访问 test->next 而不为其分配内存。您可以尝试如下更改代码以获得第二个主要工作

test = malloc (sizeof (list));
    test->val = 0;
    test->next = (list *) malloc (sizeof (list));
    ptr = test->next;
    for (i = 1; i <= 10; i++)
    {
        ptr->val = i;
    ptr->next = (list *) malloc (sizeof (list));
        ptr = ptr->next;
    }
于 2013-06-03T12:54:05.847 回答
1

看起来在第一个示例中,它ptr2在列表中保存了先前创建的节点,因此可以重写

last_created_node = test;
for (i = 1; i <= 10; i++)
{
    // create new node
    new_node = (list *) malloc (sizeof (list));
    new_node ->val = i;
    // chain newly created node onto list so far
    // make last created node point to new node
    last_created_node->next = new_node ;
    // last created node is now new node
    last_created_node = new_node ;
}
// terminate the list
last_created_node->next = 0;

在您提供的第二个代码示例中,没有等效于将新节点链接到链上的方法。正如其他人所评论的那样,统一内存也存在问题。如上面示例的最后一行所示,添加终止条件会很好。

于 2013-06-03T13:02:13.317 回答