C语言 为什么在修改链表时需要分配给指向链表的指针



在这段代码中:

void push(node **head, int data) {
    node *temp = malloc(sizeof(node));
    temp->data = data;
    temp->next = *head;
    *head = temp;
}

为什么temp->next = *head还不够?

为什么有必要将*head设置为等于temp?这究竟起到了什么作用?

方法push()接受两个参数:指向指向node的指针(指向链表的指针)的指针和要插入到列表中的值。

*head = temp;是必要的原因是,调用方的链表最终会被修改。如果没有此行,则不会修改调用方的链表。

这是一个高度简化的示例,说明为什么这是必要的。假设我有一个修改 int 的方法:

void foo(int *bar) {
    int baz;
    baz = *bar;
    baz = 42;
}

通过传入指针调用foo()后,指针指向的变量不会发生任何变化。当foo()完成时,所有堆栈变量(即 barbaz ) 将消失,对 bar 值所做的修改永远不会保存)。

回到你问题中的例子。如果该行从未被调用,则调用者的副本不会发生任何变化(即在调用函数后,就好像该元素从未添加到列表中一样),原因与调用者传递给foo()的任何内容的副本没有更改的原因相同。

因此,您经常会看到 insert() 函数的不同方法签名:

node *push(node *head, int data);

这被称为:

// assume head is a pointer to a node
head = push(head, 42);

效果是相同的,但由于只有一个指向传入节点的指针,因此push()对列表结构执行的任何操作都不会应用于head,直到分配发生。

它将头部重置为新节点,允许我们迭代所有元素。推送将新节点放在列表的开头。Head 就像一个链表的起点,使用它你可以到达所有的元素。如果 head 未设置为新节点,您将丢失对新插入数据的引用,从而导致内存泄漏。

假设它是一个基于列表的堆栈(根据Push操作进行猜测),那么该项目应该添加到列表的开头,以便可以轻松弹出。这样,当调用方尝试再次使用堆栈时,列表的头部将使用新的数据项进行更新。

相关内容

  • 没有找到相关文章

最新更新