繁体   English   中英

指针的指针:* a = b-> c和a =&b-> c之间的差异

[英]Pointers to pointers: Difference between *a = b->c and a = &b->c

回顾两星编程文章,我不禁看到以下两行之间差异的重要性:

*curr = entry->next;
curr = &entry->next;

我可以看到的唯一区别是第一行更改*curr指向下一个节点,第二行使一个全新的**指向该节点成员(这是下一循环中的上一个节点)

在我看来,在第一个if块中free条目会阻止第二行在下一个循环中正常工作,但是在那种情况下为什么不在两种情况下都只使用第一行呢? 这是性能问题吗?

编辑:请阅读上方链接中名为“两星编程”的第二个代码块

编辑:所以我似乎解释得不好(抱歉!),所以让我看看是否可以解释得更详细些。

这是本文中的源代码。

void remove_if(node ** head, remove_fn rm)
{
    for (node** curr = head; *curr; )
    {
        node * entry = *curr;
        if (rm(entry))
        {
            *curr = entry->next;
            free(entry);
        }
        else
            curr = &entry->next;
    }
}

据我估算, curr = &entry->next; 行不是必需的,您可以使用其他两次:

void remove_if(node ** head, remove_fn rm)
{
    for (node** curr = head; *curr; )
    {
        node * entry = *curr;
        if (rm(entry))
        {
            *curr = entry->next;
            free(entry);
        }
        else
            *curr = entry->next;
    }
}

然后,您可以将其移至if语句上方,并节省几行:

void remove_if(node ** head, remove_fn rm)
{
    for (node** curr = head; *curr; )
    {
        node * entry = *curr;
        *curr = entry->next;
        if (rm(entry))
        {
            free(entry);
        }
    }
}

实际上,看起来您根本不需要指针,可以做到这一点:

void remove_if(node * head, remove_fn rm)
{
    for (node* curr = head; curr; )
    {
        node * entry = curr;
        curr = entry->next;
        if (rm(entry))
        {
            free(entry);
        }
    }
}

那么为什么他们要这么做呢? 性能? 还有其他晦涩的地方吗?

两者是完全不同的。

curr = &entry->next;

接受变量entry->next的地址,并将其分配给指针变量curr 完成此任务后,以前指向的任何curr都不会更改,但将少引用它。

*curr = entry->next;

完全不更改curr的值,但是更改其指向的值,该引用的引用数与以前相同,但引用的值不同。

是的,这两个结果都将使*curr等于entry->next ,但实际上它们将不同的值写入不同的内存位置,并具有其他重要的副作用。

本文中的代码是正确的,并且所有三个建议的变体都不正确。 让我们先看一下正确的代码,并加上一些注释:

void remove_if(node ** head, remove_fn rm)
{
    // node ** passed to allow use to modify caller's head pointer
    for (node** curr = head; *curr; )
    {
        // curr is a local variable, that points to a node pointer
        // curr points either to the caller's head pointer, or to 
        // a next pointer within the list
        node * entry = *curr;
        if (rm(entry))
        {
            // remove this entry, which means modifying the list
            *curr = entry->next;
            // modify *curr modifies either caller's head pointer
            // or a next pointer
            free(entry);
        }
        else
            // did not remove, so do not modify the list
            curr = &entry->next;
    }
}

这里要注意的关键点:

  • *curr = entry->next修改列表。
  • curr = &entry->next不会修改列表。

您提出的前两个版本是错误的,因为它们确实

*curr = entry->next

在每次迭代中。 分配给*curr会修改列表。 想象一个场景,其中rm()总是返回false。 在这种情况下,您绝不能修改列表,但是每次循环时都要对其进行修改。

最终的变体是错误的,因为您只传递一个node *则无法修改调用方的头指针。 实际上,最终变体根本不会修改列表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM