【问题标题】:Weird behavior of pointer of pointer in a linked list链表中指针指针的奇怪行为
【发布时间】:2020-01-22 19:16:26
【问题描述】:

让我们考虑以下代码:

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

struct NODE {
    int value;
    struct NODE *next;
};

int prepend(struct NODE **head, int n){
    struct NODE *new_node = (struct NODE *)malloc(sizeof(struct NODE));
    if (!new_node) return -1;
    new_node->value = n;
    new_node->next = *head;
    *head = new_node;
    return 0;
}   

void pointer_address(struct NODE *head) {
    struct NODE **p_current = &head;
    struct NODE *next = NULL;
    while (*p_current) {
        printf("%p\n", (*p_current));        
        next = (**p_current).next;
        printf("%p\n\n", (*p_current));
        p_current = &(next);
    }
}

void delete_list(struct NODE *head) {
    struct NODE *current = head;
    struct NODE *next = NULL;
    while (current) {
        next = current->next;
        free(current);
        current = next;
    }
}

int main() {
    struct NODE *head = NULL;
    for(size_t i = 1; i < 10; i++) {
        if (prepend(&head, i)) {
            perror("Somenthing went wrong!\n");
            return -1;
        }
    }
    pointer_address(head);
    delete_list(head);
}

在实践中,我创建了一个链表,并在其中添加了一些整数值。但是我无法理解的是函数“pointer_address”的输出。特别是我得到

0x55871ac39360
0x55871ac39360

0x55871ac39340
0x55871ac39320

0x55871ac39320
0x55871ac39300

0x55871ac39300
0x55871ac392e0

0x55871ac392e0
0x55871ac392c0

0x55871ac392c0
0x55871ac392a0

0x55871ac392a0
0x55871ac39280

0x55871ac39280
0x55871ac39260

0x55871ac39260
(nil)

当然,每次运行程序的特定值都不同。但是,我真正无法理解的是,为什么从第二行开始,每对中的打印值都不同。它们是

的结果
printf("%p\n", (*p_current)); 

在这两种情况下。此外,我注意到从第三对开始,上面的一行等于前几行的最后一行。

问题

发生了什么事?

免责声明

我知道这段代码没有做任何有趣的事情,同样的事情可以通过其他方式完成。但是我的兴趣是了解我的代码发生了什么。

【问题讨论】:

    标签: c pointers linked-list malloc


    【解决方案1】:

    你的pointer_address 函数:

    void pointer_address(struct NODE *head) {
        struct NODE **p_current = &head;
        struct NODE *next = NULL;
        while (*p_current) {
            printf("%p\n", (*p_current));        
            next = (**p_current).next;
            printf("%p\n\n", (*p_current));
            p_current = &(next);
        }
    }
    

    产生奇怪结果的行是:

    p_current = &(next);
    

    这意味着当您更改next 的值时,*p_current 的值也会随着它们引用相同的内存而更改。所以printf 语句之间的行会改变*p_current 的值:

    next = (**p_current).next;
    

    这个函数的一个更健全的实现不会使用指向指针的指针,只需要一个指针:

    void pointer_address(struct NODE *head) {
        struct NODE *p_current = head;
        struct NODE *next = NULL;
        while (p_current) {
            printf("%p\n", p_current);        
            next = p_current->next;
            printf("%p\n\n", p_current);
            p_current = next;
        }
    }
    

    或者进一步简化:

    void pointer_address(struct NODE *p_current) {
        while (p_current) {
            printf("%p\n", p_current);        
            p_current = p_current->next;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-28
      • 2021-07-01
      • 2012-05-29
      • 1970-01-01
      • 2013-03-31
      • 2019-04-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多