为什么我的链表头指向头部之前的2个项目

时间:2017-12-10 10:16:14

标签: c pointers linked-list singly-linked-list double-pointer

所以我试图以非全局形式练习我的C双指针链表并且我很困惑为什么s - 实际上是head--首先指向null然后是一些随机地址,即使我认为我将它移动到第一个节点在列表中。

这是我的代码:

typedef struct nodeStruct{
    int               item;
    struct nodeStruct *next;
} Statistician;

void add(Statistician **s, int x);
void displayData(Statistician **s);

int main(int argc, char *argv[]) {
    Statistician *s = NULL;

    add(&s, 3); 
    add(&s, 4);
    add(&s, 5);
    add(&s, 6);
    add(&s, 7);
    add(&s, 8);
    add(&s, 9);
    displayData(&s);

    return 0;
}
void add(Statistician **s, int x){
    Statistician *temp = malloc(sizeof(Statistician));

    temp->item = x;
    temp->next = NULL;

    if(s == NULL){
        s = &temp;
    }
    else{
        Statistician *travel = s;

        while(travel->next!=NULL){
        travel = travel->next;
    }

    travel->next = temp;
   }
 }

 void displayData(Statistician **s){
    Statistician *temp = s;

    printf("List is: ");

    while(temp!=NULL){
    printf("%d ", temp->item);
    temp = temp->next;
    }
 }

我从我的代码中得到了这个输出,我也得到了这些警告: List is: 0 43586480 3 4 5 6 7 8 9 [警告]在此行代码中从不兼容的指针类型[默认启用]进行初始化 统计学家* travel = s

我可以在打印数据之前总是移动displaydata两次,这样第一个我不想看到的就不会出去但我想知道为什么它的工作方式就是这样。我也可以忽略这些错误,但我想学习如何修复它。

2 个答案:

答案 0 :(得分:2)

  

[警告]在此代码行中从不兼容的指针类型[默认启用]进行初始化Statistician * travel = s

这表示您正在分配不兼容的指针类型。

if(s == NULL){
    s = &temp;
}

此处s未指向您的head*s是。 所以它应该是

if(*s == NULL){
*s = temp;
}

然后

Statistician *travel = s;

同样应该是

Statistician *travel = *s;

然后在displayData()

void displayData(Statistician **s){
Statistician *temp = *s;

答案 1 :(得分:1)

代码逻辑错误。你没有正确使用s。它会是这样的。您之前的操作没有做任何重要的事情。您对局部变量进行了一些错误的更改,并为双指针指定了单个指针值。

void add(Statistician **s, int x){
    Statistician *temp = malloc(sizeof(Statistician));

    temp->item = x;
    temp->next = NULL;

    if(*s == NULL){
        *s = temp; //<---change 
    }
    else{
        Statistician *travel = *s; //<--change

        while(travel->next!=NULL){
        travel = travel->next;
       }

    travel->next = temp;
   }
 }

您需要检查malloc呼叫是否失败,方法是检查其重新定时值。当调用失败时,这将使您免于未定义的行为。

同样displayData功能也是错误的。这将是

 void displayData(Statistician **s){
    Statistician *temp = *s; //<---change

    printf("List is: ");

    while(temp!=NULL){
    printf("%d ", temp->item);
    temp = temp->next;
    }
 }

之前您有未定义的访问内存的行为,您甚至没有分配,或者您没有权限。这在您的代码中调用了未定义的行为。

清除这个想法:

当您传递&s时,这表示正在发送s的地址,类型为Statistician**的本地变量将保留该地址。现在,如果你没有取消引用它,那么你只需使用局部变量中包含的s地址。这不是你想要的。您需要更改正在传递的地址。所以你可以通过解除引用*s = temp来做到这一点。