为什么我的链表头指向头前的2项

Why does my linked list head point to 2 items before the head

所以我尝试以非全局形式练习我的 C 双指针链表,我很困惑为什么 s——实际上是头——先指向 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

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

代码逻辑错误。你没有正确使用 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 并像这样。

[Warning] initialization from incompatible pointer type [enabled by default] at this line of code 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;