C 不确定我为什么会在这里出现分段错误

C 不确定我为什么会在这里出现分段错误,c,list,linked-list,segmentation-fault,nodes,C,List,Linked List,Segmentation Fault,Nodes,我知道我可以更改代码来修复错误,但我不明白为什么会出现分段错误。非常感谢您的帮助,谢谢 typedef struct nodes{ int data; struct nodes *next; } node; int main(int argc, char * argv[]){ node *head = NULL; node *tmp = NULL; int i; head = malloc(sizeof(node)); tmp = he

我知道我可以更改代码来修复错误,但我不明白为什么会出现分段错误。非常感谢您的帮助,谢谢

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

int main(int argc, char * argv[]){
    node *head = NULL;
    node *tmp = NULL;
    int i;

    head = malloc(sizeof(node));
    tmp = head;
    for(i = 0; i < 10; i++){
        tmp->data = i;
        tmp->next = malloc(sizeof(node));
        tmp = tmp->next;
    }
    tmp = NULL;
    for(tmp=head; tmp->next != NULL; tmp = tmp->next){
        printf("%d\n", tmp->data);
    }

}

最后一个节点的
next
指针未设置为
null
。因此,条件
tmp->next!=对于
,第二个
中的NULL
-将永远不会满足循环。实际上,您可以看到,在seg故障发生之前,在最后一个数字(
9
)之后会打印一些垃圾编号(
0

执行此操作时:

tmp->next=malloc(sizeof(node))

您还应该添加如下内容:

node *head = NULL;
for (int i = 9; i >= 0; i--)
{
    node *tmp = malloc(sizeof(node));
    tmp->data = i;
    tmp->next = head;
    head = tmp;
}
tmp->next->next=NULL

通过这种方式,您可以“安全地”初始化每个节点,并将
next
-指针设置为
NULL
。除最后一个节点外,所有节点都将在下一次迭代中获得正确的值

编辑正如@Someprogrammerdude在评论中指出的那样,即使按照上面的建议操作,最终也会有一个额外的节点。 要解决此问题,可以按如下方式更改创建循环:

for(i = 0; i < 10; i++){
    tmp->data = i;
    if (i < 9) {
        tmp->next = malloc(sizeof(node));
    } else {
        tmp->next = NULL;
    }
    tmp = tmp->next;
}
(i=0;i<10;i++)的
{
tmp->data=i;
如果(i<9){
tmp->next=malloc(sizeof(node));
}否则{
tmp->next=NULL;
}
tmp=tmp->next;
}

通过向后构建列表,您将获得稍微干净的代码。换句话说,首先将最后一个节点添加到列表中,然后在列表的开头插入其他节点。代码如下所示:

node *head = NULL;
for (int i = 9; i >= 0; i--)
{
    node *tmp = malloc(sizeof(node));
    tmp->data = i;
    tmp->next = head;
    head = tmp;
}

请注意,由于
head
最初是
NULL
,因此列表中的最后一个节点将其
next
指针设置为
NULL
。这就是代码中缺少的内容。

实际上,整个循环及其分配都是错误的。如果OP试图创建一个包含十个节点的列表,那么“最后”(第十个)节点将有一个指向第十一个节点的指针,而没有初始化的
数据
下一个
成员。@Someprogrammerdude:很好,你是对的,即使我提出了解决方案,他最终也会得到“垃圾”节点。我将编辑答案来指出这一点。有没有更有效的方法来代替检查'iA simple
tmp->next=NULLfor
之后,code>循环就足够了。