2017-10-10 63 views
-1

我目前正在尝试学习如何链接列表作为个人项目。我了解核心概念,并一直试图将其实施到c。我的程序看起来应该可以工作,请记住我仍然是编程新手:D在函数中使用双指针

我创建了一个名为head的结构指针。 head将指向linked_list中的第一个节点,startPtr将包含head的地址。每次调用函数add时,都会创建一个新节点并在内存中分配一些空间,然后之前创建的节点将指向新节点。

我知道我的程序在哪里崩溃,但我可以看到为什么?它编译好。上线

(*prevNode)->link = newNode; 

我的代码崩溃是我看到这个代码的方式:我通过双指针startPtr到函数添加 。然后我使用malloc创建了一个新节点。接下来我参考startPtr(它在函数中被称为prevNode),它应该包含head的内存地址....对吧?然后我使用“ - >”表达式来指向称为链接的头内的结构指针。

程序只是在这一点结束,我不知道为什么。我查看了其他链表的c代码,但其中大多数不使用双指针,他们只是声明全局结构和指针。我使用GCC作为我的编译器。

任何人都知道为什么会发生这种情况?

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


// STRUCTURES 

struct node 
{ 
    int data; 
    struct node *link; 
}*head; 

void add(int, struct node **); 


int main() 
{ 
    struct node *head; 
    struct node **startPtr; 
    startPtr = head; 
    struct node *nodePtr; 
    int userInput; 
    int inputData; 


    do{ 
    printf("\n\n1: enter new node\n"); 
    printf("2: Print Nodes\n"); 
    printf("\n\nEnter: "); 
    scanf("%d", &userInput); 
     if (userInput == 1) 
     { 
      printf("\n\nEnter data:"); 
      scanf("%d", &inputData); 
      add(inputData, startPtr); 
     } 

    }while(userInput == 1); 

    // printing linked list 
    nodePtr = head->link; 
    while(nodePtr->link != NULL) 
    { 
     printf("%d\n", nodePtr->data); 
     nodePtr = nodePtr->link; 
    } 
    printf("%d\n", nodePtr->data); 
    return 0; 

}// END main() 

void add(int num, struct node **prevNode) 
{ 
    // assigning memory for a new node 
    struct node *newNode = malloc(sizeof(struct node)); 
    (*prevNode)->link = newNode;   
    newNode->data = num;   
    newNode->link = NULL;   
    prevNode = &newNode; 
}// END add() 

另外我有一个其他问题,我无法找到并在网上回答。当我创建一个指向结构的指针时,例如struct node * ptr ;. structer指针默认存储它自己的地址。通过它的自我我的意思是结构,所以如果我打印ptr会输出structer ptr的地址吗?

+0

除此之外,你的add()函数也被窃听(它的分配prevNode不会改变调用者的变量)。 – jarmod

+0

对不起,我早上在乱搞,我必须删除它。我编辑了我的代码。我是编码新手,所以我不确定你的意思。我以为因为我传递了一个指针,所有在该函数中做出的改变都会被写入指针地址的内存位置。 –

+1

为什么重新打开?这是不是重复的“我试图将数据存储到单位化指针的地址”?我们不需要解释为什么每天10次没有意义。存在典型重复是有原因的。 – Lundin

回答

1

除了这个错字

startPtr = head; 
      ^^^^ 

哪里有要

startPtr = &head; 
      ^^^^^ 

有几个问题的代码。

第一个问题是标题最初没有初始化。所以取消引用这个指针会导致未定义的行为。

的第二个问题是,这个循环

do{ 
printf("\n\n1: enter new node\n"); 
printf("2: Print Nodes\n"); 
printf("\n\nEnter: "); 
scanf("%d", &userInput); 
    if (userInput == 1) 
    { 
     printf("\n\nEnter data:"); 
     scanf("%d", &inputData); 
     add(inputData, startPtr); 
    } 

}while(userInput == 1); 

是建立在逻辑上不正确。例如,如果用户输入的数字不等于1或2,那么程序将在退出循环后尝试输出列表。

第三个是最初头可以等于空。所以在功能

(*prevNode)->link = newNode; 

这一说法再次调用未定义的行为,而且如果*prevNode不等于空,则所有早期的附加节点都将丢失,因为其参考link被覆盖。

功能可以从头部未初始化看看下面的方式

int add(struct node **head, int data) 
{ 
    struct node *newNode = malloc(sizeof(struct node)); 
    int success = newNode != NULL; 

    if (success) 
    { 
     newNode->data = data; 
     newNode->link = *head; 
     *head = newNode; 
    } 

    return success; 
} 
+0

第一个问题是代码首先不能编译,因为它不是有效的C.'startPtr = head;'这些是不兼容的指针类型。该行违反了简单赋值的约束条件。 – Lundin

+0

@Lundin我认为这只是一个错字,因为从它的帖子来看,这是一个分段错误。 –

1
struct node *head; 

从未初始化

startPtr = head; 

初始化为未初始化的;除此之外,你的整个程序是不确定的。

+0

这就是为什么程序崩溃的原因'(* prevNode) - > link = newNode;'这就是为什么当数据被复制/扫描/读取到未初始化的指针时,问题与[崩溃或“段错误” ](https://stackoverflow.com/questions/37549594/crash-or-segmentation-fault-when-data-is-copied-scanned-read-to-an-uninitializ)。 – Lundin

2

很多在这里解开......这些都是初始化,然后你别名指针,而不是指向一个地址,所以你真的没有指针的指针,你有相同的指针2

struct node *head; 
struct node **startPtr; 
startPtr = head; 
struct node *nodePtr; 

也许是这样的:

struct node *head = NULL; 
struct node **startPtr = &head; 
struct node *nodePtr = NULL; 

将是一个更好的开始...然后用C,所以你必须先检查是否有一个空指针的可能性不能DEREF NULL指针。 ..注意这不会检查未初始化的垃圾值,该局部变量可以是:

if(startPtr && *startPtr) 
{ 
// now you know you can deref startPtr twice, 
// once to a pointer to an object (which might be null) 
// then after then && you can deref to an actual object 
} 
+0

'startPtr = head;'甚至不是有效的C.这些不是兼容的指针类型。该行违反了简单赋值的约束条件。 – Lundin