【问题标题】:Cannot create a linked list from NULL无法从 NULL 创建链表
【发布时间】:2021-10-01 06:29:13
【问题描述】:

在下面的代码中,我在函数main 中声明了一个二进制链表Node *node = NULL,并打算在函数Test 中创建一个节点。在那之后,node 仍然是NULL。为什么?

#include <stdlib.h>

typedef struct Node {
    int value;
    struct Node *left, *right;
} Node;

int Test(Node* node) {
    node = malloc(sizeof *node);
    node->value = 1;
    node->left = NULL;
    node->right = NULL;
    return 0;
}

int main() {
    Node* node = NULL;
    Test(node);
    if(node) {
        putchar('0' + node->value);
    } else {
        putchar('n');
    }
    free(node);
    return 0;
}

为什么这段代码打印的是n 而不是1

【问题讨论】:

  • 请记住,在 C 中,所有函数参数都是按值传递。这意味着参数的值被复制到函数的参数变量中。如果函数修改了参数变量,只有这个变量被修改,调用中使用的原始变量将不会被修改。请做一些关于在C中模拟reference传递的研究。
  • 请注意,如果您使用像 Valgrind 这样的动态分析工具,您也可能会发现您的假设有问题。它会告诉您内存泄漏,暗示它没有按您的预期工作。
  • 我的建议是返回节点而不是传递它。所以你会有Node* Test(void); 并在main 函数中做Node* node = Test();
  • 我喜欢你小心翼翼地不得到未初始化的值;这是一个可靠的实验。 node 中的 Testnode 中的 main 恰好同名。

标签: c linked-list


【解决方案1】:

这是因为参数是按值传递的。因此,当您将节点作为参数传递给函数时,实际的 NULL 值将被传递,对该值所做的任何更改都不会影响函数外部的节点变量。

【讨论】:

    【解决方案2】:

    您必须通过引用而不是值来复制节点 ptr。这是一个很好的例子,说明为什么指针被认为是困难的(也是我使用 C++ 的一个原因)。 您已成功更改测试中的节点,但“主”中的变量节点和“测试”中的节点不同。

    测试应该是这样的

    int Test(Node** node) {
        *node = malloc(sizeof *node);
        (*node)->value = 1;
        (*node)->left = NULL;
        (*node)->right = NULL;
        return 0;
    }
    

    并调用测试

    Test(&node);
    

    【讨论】:

    • 有时接受双指针是有意义的,但我肯定会停下来看看是否有更好的方法。在这种情况下,返回指针可能是更自然的设计决策。
    猜你喜欢
    • 2015-02-14
    • 2020-08-08
    • 2021-08-12
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-14
    相关资源
    最近更新 更多