使用指针指针有什么意义?

时间:2017-08-31 22:26:06

标签: c pointers linked-list insertion

我在网站上发现了这个代码,用于在列表开头的链表中插入节点。

void push(struct Node** head_ref, int new_data)
{
/* 1. allocate node */
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));

/* 2. put in the data  */
new_node->data  = new_data;

/* 3. Make next of new node as head */
new_node->next = (*head_ref);

/* 4. move the head to point to the new node */
(*head_ref)    = new_node;
}

这是函数调用 -

push(&head, 7);

我的问题是为什么要通过传递指针的地址然后随后在函数内的地址处提取值来实现目标。 为什么我们不能简单地在函数中传递指针head,然后像 -

那样进行赋值
new_node->next=head_ref;

4 个答案:

答案 0 :(得分:3)

如果您通过了head而非&head,那么

(*head_ref)    = new_node;

必须更改为

head_ref    = new_node;

然而,这将是功能的局部变化。它不会更改调用函数中head的值。这有两个问题:

  1. 调用函数永远不会得到工作列表。
  2. 在函数中分配的内存将是内存泄漏。

答案 1 :(得分:2)

您也可以按如下方式编写代码:

struct Node* push(struct Node* head_ref, int new_data)
{
    struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
    new_node->data = new_data;
    new_node->next = head_ref;
    return new_node;
}

并按如下方式调用:

head = push(head, 7);

它实现了完全相同的功能,即在列表的头部插入一个新节点,然后更新head以指向该新节点。但是在我看来,它并不是一个好的解决方案,因为它允许push()函数的调用者忘记将返回的值赋给head,此时你将拥有孤立的节点和最终内存泄漏。

答案 2 :(得分:0)

调用程序中的变量头是指向列表头部的指针。您需要一个指向此变量的指针,以便在push()中更新它。因此,您将指针传递给包含指针的变量,以便您可以更新该变量。

答案 3 :(得分:0)

这一切都与您选择的编程风格有关。使用一组函数来操作列表使程序结构合理。这样你就可以使它更具可读性。如果您需要从多个位置操作相同的列表或操作多个列表,它还将避免剪切粘贴。

您整理功能的方式取决于您。我个人喜欢你的例子中的方式。在这种情况下,您只需在参数中指定一次指向头部的指针。如果从函数返回它,则在程序中使用错误指针的风险更高。

'C'有足够的工具来编写任何类型的程序。但是,有时您需要遵循特定的规则来应用它们,例如您的案例中指针的地址。不太方便但可靠并且证明可行。作为一名'C'程序员,你会很快习惯它。

您还可以查看c ++,它有更好的工具,使这更方便。