尝试访问 '''list1->data''' [duplicate] 时出现分段错误

segmentation fault when trying to access ```list1->data``` [duplicate]

提问人:ryden 提问时间:1/26/2022 最后编辑:Vlad from Moscowryden 更新时间:1/26/2022 访问量:41

问:

我对 C 有点陌生,所以这个问题听起来可能太容易了。

我尝试运行这个简单的程序,但遇到了分段错误:

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

void makeList(struct list* list1) {
    list1 = (struct list*) malloc(sizeof(struct list));
    list1->next = NULL;
}

int main(int argc, char ** argv) {
    struct list * list1;
    makeList(list1);
    list1->data = 5;
    printf("data: %d\n", list1->data);

    return 0;
}

我知道问题出在主要,但为什么呢?list1->data = 5

在我看来,该函数获取结构列表的指针并为其分配存储空间。这就是我所做的,不是吗?我经过了指针。为什么它表现得像 list1 没有初始化或其他什么?为什么它不起作用?makeListlist1

C 指针 struct 按值传递 函数定义

评论

1赞 Fred Larson 1/26/2022
list1实际上在 中未初始化。 仅分配本地指针。main()makelist()
1赞 Eugene Sh. 1/26/2022
list1通过传递给 ,并且您在函数中分配给它的任何内容在外部都不可见。makeList
0赞 ryden 1/26/2022
按价值?但是在是一个指针,不是吗?它有这个东西。我该如何解决?如何通过引用/指针传递它?list1main()*
1赞 Fred Larson 1/26/2022
是的,但这是您尝试更改的指针,而不是指向的项,并且指针是按值传递的。所以你可以使用双指针,但在这种情况下,我想我更喜欢 Vlad 返回指针值的解决方案。
0赞 yano 1/26/2022
指针没有什么特别之处。如果你这样做,你会看到。这是因为 的副本在 中被修改了,并且该副本在返回时死亡/超出范围。与您在这里所做的相同,只是使用指针。要使更改保留在 C 中的函数之外,您需要返回一个值或传递指向要修改的内容的指针,然后取消引用并修改它指向的内容。int i=4; add5(int i) { i += 5; } printf("i==%d\n", i);i==4iadd5add5

答:

2赞 Vlad from Moscow 1/26/2022 #1

在此声明中

struct list * list1;

声明了一个未初始化的指针,因此具有不确定的值。

在此函数的调用中makeList

makeList(list1);

传递了指针值的副本。因此,该函数更改的是值的此副本,而不是原始指针。在 main 中声明的原始指针保持 unchenged。list1

例如,您可以按以下方式声明和定义函数

struct list * makeList( void ) 
{
    struct list *list = malloc( sizeof( struct list ) );
    if ( list != NULL ) list->next = NULL;

    return list;
}

在主要情况下,该函数被称为

list1 = makeList();

另一种方法是通过引用将 main 中声明的指针传递给函数。在 C 语言中,通过引用传递意味着通过指向对象的指针间接传递对象。取消引用指针可以访问原始对象。

例如

void makeList( struct list **list ) 
{
    *list = malloc( sizeof( struct list ) );
    if ( *list != NULL ) ( *list )->next = NULL;
}

该函数称为

makeList( &list1 );

评论

0赞 ryden 1/26/2022
谢谢你的解释。这是否意味着必须返回?不能是无效的吗?我知道在 Java 中这是可能的,对吧?makeListstruct list*
1赞 Vlad from Moscow 1/26/2022
@ryden 如果要将函数声明为返回类型为 void,则需要通过指向它的指针通过引用传递指针。
0赞 ryden 1/26/2022
你能告诉我它应该是什么样子吗?按引用传递指针
0赞 Vlad from Moscow 1/26/2022
@ryden 请参阅我更新的帖子。