C使用指向第一个节点(头节点)指针的指针打印单链表时出现分段错误

C使用指向第一个节点(头节点)指针的指针打印单链表时出现分段错误,c,pointers,linked-list,C,Pointers,Linked List,目标:创建单个链接列表,并使用头指针(而不是头节点)打印列表 **开始: 是头节点(第一个节点)指针 我不想将头节点(第一个节点)存储为*start,而是想将头节点指针存储为**start ALG: 创建包含五个节点的列表(在我的程序中硬编码) 使用指向头部节点的指针显示它们 代码中有一个明显的漏洞,不容易出现。 有人能提供你的意见吗 #include <stdio.h> #include <stdlib.h> struct node { int d

目标:创建单个链接列表,并使用头指针(而不是头节点)打印列表

**开始

  • 是头节点(第一个节点)指针

  • 我不想将头节点(第一个节点)存储为
    *start
    ,而是想将头节点指针存储为
    **start

ALG:

  • 创建包含五个节点的列表(在我的程序中硬编码)
  • 使用指向头部节点的指针显示它们
  • 代码中有一个明显的漏洞,不容易出现。 有人能提供你的意见吗

    #include <stdio.h>
    #include <stdlib.h>
    
    struct node {
            int data;
            struct node *link;
    }**start;
    
    
    void display(void) {
            struct node *p;
    
            if (!strart ) { printf("List is empty\n"); return; }
            p = *start;
            printf("List :");
            while(p != NULL) {
                    printf("-%d", p->data);
                    p = p->link;
            }
            puts("");
    }
    
    struct node **createlist(void) {
            int n;
            struct node *p, *new, *tmp; 
    
            printf("enter no of elements to add\n");
            //scanf("%d", &n);
    
            p = NULL;
            n=5;
            while(n--) {
                    new = (struct node *) calloc(1, sizeof(struct node)); 
                    new->data = n;
                    if (p) {
                            p->link = new;
                            p = new;
                    } else if (p == NULL) {
                            p = tmp = new;
                    }
            }
            printf("before assign start :%p\n", start);
            start = &tmp;
            printf("after assign start :%p\n", start);
            printf("In create List :\n");
            display();
    
            return start; 
    }
    int main() {
    
            int ch;
            do {
                    printf("1.CreateList 2.DisplayList\n");
                    //scanf("%d", &ch); //HARDCODED
    
                    switch(1) {
                            printf("switch -> start :%p\n", start);
                            case 1 : start = createlist();
                            printf("after create -> start :%p\n", start);
                            case 2 : printf("Disp:\n"); display(); break;
                            default : printf("Invalid option\n");
                    }
            } while(0);
    
            return 0;
    }
    

    在这里,您可以指定一个临时函数本地对象的地址:

       start = &tmp;
    
    稍后返回该地址:

        return start;
    
    从此点开始,返回的指针指向不再存在的对象

    我不清楚为什么将
    start
    声明为
    struct节点**
    。你说:

    **开始:是头节点(第一个节点)指针

    。。。但事实并非如此<代码>**start是一个节点,而不是指针<代码>*开始可以指向第一个节点<代码>开始声明为指向节点指针的指针

    我不想将头节点(第一个节点)存储为*start,而是将头节点指针存储为**start

    你不能;正如声明的那样,它不是正确的类型<代码>**start是一个节点,不能在其中存储节点指针
    *start
    是指向节点的指针,
    start
    是指向节点指针的指针

    我真的认为
    start
    应该声明为
    struct节点*
    ,而不是
    struct节点**
    。你似乎误解了双星的含义。

    问题就出现在这里 随着函数createlist()的返回,它的堆栈帧被销毁,甚至变量temp也被销毁。所以temp变量不存在了,列表的第一个节点的地址在temp中,所以主函数中的值*start变为零,访问元素时总是出现分段错误

        start = &tmp;
        printf("after assign start :%p\n", start);
        printf("In create List :\n");
        display();
    

    要克服此问题,请使用全局头指针保存第一个节点的地址,或者可以将tmp变量设置为全局。

    使用
    valgrind
    。使用调试器。
    struct node**createlist(void)
    将指针返回到指针在这里没有什么意义。
        start = &tmp;
        printf("after assign start :%p\n", start);
        printf("In create List :\n");
        display();