Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 链表中的分段错误_C - Fatal编程技术网

C 链表中的分段错误

C 链表中的分段错误,c,C,我首先使用initlist创建了一个线性链表,然后使用listlength返回0,但调试时出现了分段错误。为什么? 代码在这里 #include<stdio.h> #include<stdlib.h> typedef struct LNode{ int data; struct LNode *next; }LNode,*LinkList; int InitList(LinkList L); int ListLength(LinkList L); int m

我首先使用initlist创建了一个线性链表,然后使用listlength返回0,但调试时出现了分段错误。为什么? 代码在这里

#include<stdio.h>
#include<stdlib.h>
typedef struct LNode{
    int data;
    struct LNode *next;
}LNode,*LinkList;
int InitList(LinkList L);
int ListLength(LinkList L);
int main(void)
{
    LinkList L;
    InitList(L);
    printf("%d",ListLength(L));
    return 0;
}
int InitList(LinkList L){
    L=(LinkList)malloc(sizeof(LNode));
    if(!L)return 0;
    (L->next)=NULL;
    return 1;
}
int ListLength(LinkList L)
{
    int length=0;
    if((L->next)==NULL) return 0;
    struct LNode *x=(L->next );
    while(x){
        length++;
        x=x->next ;
    }
    return length;
}

甚至第一个函数
InitList
也不正确,没有意义

首先,它处理在main中声明的指针
L
的值的副本,该值用作参数。因此,在函数中更改副本不会影响原始指针
L
。它保持未初始化状态,具有不确定的值

只需将main中的指针
L
设置为
NULL
。这将是列表的初始化

LinkList L = NULL;
当列表总是有一个伪节点,该节点由指针
L
指向,且始终不等于NULL时,这种方法太复杂,只会混淆代码的读者

相应地,您需要将函数
ListLength
中的当前检查(if语句中的条件)更改为检查传递的指针是否不等于NULL,因为现在列表没有虚拟节点

请注意,使用这样的typedef不是一个好主意

typedef struct LNode{
    int data;
    struct LNode *next;
}LNode,*LinkList;
例如,函数
ListLength
不会更改列表本身。所以它的参数至少应该声明为

int ListLength( const LNode *L );
但是如果你愿意写

int ListLength( const LinkList L);
那么它就意味着一个不同的声明,相当于

int ListLength( LNode * const L );

欢迎来到SO。在C语言中,所有参数都是按值传递的,即向被调用函数提供一个副本。在函数内部对该参数所做的任何操作都不会对该函数外部产生任何影响。在您的情况下,
L
不会被
InitList
更新。这意味着您有一个未初始化的指针
L
,您将其传递到
ListLength
,在那里它被取消引用,从而导致问题。在取消引用指针之前,还应添加对
NULL
的检查。(在这种情况下这不会有帮助)这也可能有帮助:不相关的,任何人告诉你在typedef别名中隐藏指针类型(例如
LinkList
)是一个好习惯都是错误的。有两个地方值得注意:blackbox句柄类型API和回调函数指针类型。此代码不显示这两个属性。经典错误。C使用传递值。换句话说:
inyList
将不会在
main
中更新
L
,如果您定义结构如
typedef struct LNode{int data;struct LNode*next;}LNode,LinkList并在主界面中使用,如
链接列表*L
和n方法declation使用
int InitList(LinkList*L)
它应该可以工作。他的
ListLength
函数仍然会崩溃。@kfx你错了。当他的列表总是有一个不等于NULL的伪节点时,他使用了一种方法。我可以改为int InitList(LinkList&L)吗?@Weng,因为我写的函数没有意义。不需要创建虚拟节点。您需要的是在主链接列表中写入L=NULL;这就足够了。您正确地指出了
InitList
的问题,但我不明白为什么您认为将L设置为NULL就足够了。我邀请您运行并编译代码。
int ListLength( LNode * const L );