我从linus on understanding pointers获得了以下代码。
typedef struct list_entry {
int val;
struct list_entry *next;
} list_entry;
list_entry **pp = &head; /* pointer to a pointer */
list_entry *entry = head;
while (entry) {
if (entry->val == to_remove)
*pp = entry->next; //6
pp = &entry->next; //8
entry = entry->next;
}
有人可以帮助理解第6和第8行吗?如果entry-> val == to_remove,则评估第6行,并且* pp成为删除后的下一个条目,那么第8行之后会做什么?当前条目已被删除,如何在第8行重新使用此条目?
另外,我知道* pp表示指针pp的值,而& entry-> next表示pp的地址,我总是对何时使用*以及何时&应该使用。具体来说,第6行可以是:
pp = &entry->next;
和第8行是:
*pp= entry->next;
如果没有,为什么?
答案 0 :(得分:1)
更新
博客中的代码不完整,并假设只删除一个元素,并且不需要免费。如果要删除两个或多个连续元素,则序列中的第二个元素将不会被删除。
正确的代码是,也假设不必释放节点:
while (entry) {
if (entry->val == to_remove)
*pp = entry->next;
else
pp = &entry->next;
entry = entry->next;
}
如果你必须释放节点:
while (entry)
{
if(entry->value == to_remove )
{
*pp = entry->next;
free( entry ) ;
entry = *pp ;
}
else
{
pp = &entry->next;
entry = entry->next;
}
}
编写整个结构确实有助于理解这一点。
struct Node
{
int val ;
struct Node* next ; //hint, this has an address too.
} ;
诀窍在声明中
pp = &entry->next ;
这看起来像是指向next
节点,但实际上你只是获取当前节点指针的地址。 差异很大!
因此pp = &entry->next ;
几乎等同于第一个示例中的prev = entry;
,唯一的区别是您指向当前next
的成员struct Node
的地址指向整个当前struct Node
。
答案 1 :(得分:0)
在此示例代码中,pp存储了' next'的地址。上一个链的成员,以便在当前链标记为删除的情况下,然后' next'可以修改前一个链的成员以指向“下一个”'现在被删除的链。间接修改是通过应用*运算符完成的。
第6行和第8行不能根据您的问题进行修改,因为代码将无法达到预期的效果。
保留' next'的地址前一个(或头)链的成员。
检查当前链是否标记为要删除。
如果是,那么使用pp引用间接操纵前一个链接下一个'会员指向' next'当前,所以实际上链表将跳过当前链,同时保持其完整性。
答案 2 :(得分:0)
这里发生了什么:
list_entry **pp = &head; /* pointer to a pointer */
list_entry *entry = head;
// we start with entry being head and pp being an address of head
while (entry) {
// while there is a list_entry which is not NULL...
if (entry->val == to_remove)
// if entry points to value that should be removed,
// then store the address of the next entry in whatever pp points to now
// (which effectively means removing that entry)
*pp = entry->next; //6
// pp is now an address of the next entry
pp = &entry->next; //8
// move to the next entry to start the next iteration
entry = entry->next;
}
此代码的作用:它遍历列表并删除所有标记为已删除的条目。
它是如何做到的:
最初,pp
指向头部。
从头开始,它会越过列表。
只要当前条目指向的值标记为“已删除”,pp
就会在当前列表条目的地址中存储下一个列表条目的地址。如果pp
指向头部,则意味着头部被丢弃并且它开始指向下一个元素。如果pp
指向列表中间的元素,则表示此元素已被删除(因为现在前一个元素将指向被删除元素之后的元素。)
完成后,它会移动entry
点以检查列表中的下一个值。
答案 3 :(得分:-1)
&
表示返回某些内容的地址。 *
表示访问指针指向的变量。
所以行:
pp = &entry->next;
*pp= entry->next;
不同。
第一个设置指针包含entry->next
的地址,而第二个设置pp
指向的变量的值等于entry->next
。
entry->next
被删除"之后可以被引用的原因是因为当它从链表中删除时,它仍然存在于内存中,仍然可以被访问。 / p>