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

时间:2016-10-19 10:15:31

标签: c pointers linked-list

目标:创建单个链表并使用HEAD POINTER(而不是HEAD NODE)打印列表。

**start

  • 是HEAD NODE(FIRST NODE)指针

  • 而不是将HEAD NODE(FIRST NODE)存储为*start,我想将HEAD NODE指针存储为**start

ALG:

  1. 创建包含五个节点的列表(在我的程序中硬编码)。
  2. 使用指向HEAD NODE
  3. 的指针显示它们

    代码中有一个重要的HOLE,它看起来并不容易。 任何人都可以就此提出意见。

    #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;
    }
    

    代码输出:

    root@CDrive:~/datastructures# ./a.out 
    1.CreateList 2.DisplayList
    enter no of elements to add
    before assign start :(nil)
    after assign start :0x7ffd13e64798
    In create List :
    List :-4-3-2-1-0
    after create -> start :0x7ffd13e64798
    Disp:
    Segmentation fault (core dumped)
    

2 个答案:

答案 0 :(得分:0)

在这里,您为start分配临时的,函数本地对象的地址:

   start = &tmp;

稍后您将返回该地址:

    return start;

从这一点开始,返回的指针指向一个不再存在的对象。

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

  

** start:是HEAD NODE(FIRST NODE)指针

......但事实并非如此。 **start是一个节点,而不是指针。 *start 可以指向第一个节点。 start被声明为指向节点的指针。

  

而不是将HEAD NODE(FIRST NODE)存储为* start,我想将HEAD NODE指针存储为** start

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

我认为start可能应该被声明为struct node *而不是struct node **。你似乎误解了双星意味着什么。

答案 1 :(得分:0)

问题出在这里 随着函数createlist()的返回,它的堆栈框架被破坏,甚至变量temp也被破坏。因此,临时变量不再存在,并且我们将列表的第一个节点的地址设置为temp,因此在主函数中值* start变为零,并且访问元素始终存在分段错误。

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

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