一个基本的例子 C 链表计数代码总是抛出分段错误

A basic example c linked lists count code always throw segmentation fault

我有以下代码

 /*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * File:   index.c
 * Author: nikos
 *

 * Created on May 6, 2016, 9:19 AM
 */

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

/*
 *
 */
struct people {
    int age;
    char *name;
    struct people * next;
};
typedef struct people people;

void count(people person) {
    people *current;
    people *next;
    current = &person;
    next = person.next;
    int count = 1;
    while (current) {
        printf("age : %d\n", current->age);
        printf("name : %s\n", current->name);
        count++;
        current = next;
        if (next->next != NULL) {
            next = next->next;
        } else {
            next = NULL;
        }
    }
    printf("%d\n", count);
}

int main(int argc, char** argv) {
    people person = {
        .name = "nikos",
        .age = 25
    };
    person.next = malloc(sizeof (people));
    person.next->age = 26;
    person.next->name = "test";
    person.next->next = NULL;
    count(person);
    return 0;
}

当我 运行 这样做时,它 运行 循环并打印列表的内容,但是当它命中 null 时会出现段错误。

我不明白为什么在我看来 c 有问题。

这是非常基本的逻辑,检查下一个内容,如果它为 null 则停止循环,否则继续下一步。

不要为了简单的事情写复杂的代码,尽量写的简单。试图理解你的代码,知道它想要实现一个简单的事情是如此困难,我立即看到了一种编写它的方法,它可以使逻辑清晰并防止任何愚蠢的错误,检查一下

void
count(people person)
{
    int count = 0;
    for (people *node = &person ; node != NULL ; node = node->next)
    {
        printf("age : %d\n", node->age);
        printf("name : %s\n", node->name);

        count++;
    }
    printf("%d\n", count);
}

int
main(void)
{
    people person = {.name = "nikos", .age = 25};

    person.next = malloc(sizeof(people));
    if (person.next == NULL)
        return -1;

    person.next->age = 26;
    person.next->name = "test";
    person.next->next = NULL;

    count(person);

    return 0;
}

您的代码失败,因为您将 next 设置为 NULL

next = NULL;

然后尝试在

中取消引用它
if (next->next != NULL)

你应该在 while 条件语句中检查 next == NULL

while ((current != NULL) && (next != NULL))

但该代码仍然非常复杂和繁琐。

看到那个

if (next->next != NULL)
    next = next->next;
else
    next = NULL;

效果完全一样
next = next->next;

当您显示列表中的最后一项时,next 为 NULL,因此尝试在 'if' stmt 中引用 next->next 实际上是在说 NULL->next!这是你的段错误。不必要的逻辑复杂性使其变得格外难以看清,但这就是正在发生的事情。