*indirect = entry->next; 求值时会发生什么?我不明白为什么它会导致删除某些条目。
希望你对双指针有清晰的认识1).
假设如下:
节点结构是
typedef struct Node {
int data;
struct Node *next;
} linked_list;
并且链表有5 节点和指向列表中第二个节点的entry 指针。内存中的视图是这样的:
entry -+
head |
+---+ +-------+ +-------+ +-------+ +-------+ +--------+
| |---->| 1 | |---->| 2 | |---->| 3 | |---->| 4 | |---->| 5 |NULL|
+---+ +-------+ +-------+ +-------+ +-------+ +--------+
此声明:
linked_list** indirect = &head;
将使indirect 指针指向head。
entry -+
head |
+---+ +-------+ +-------+ +-------+ +-------+ +--------+
| |---->| 1 | |---->| 2 | |---->| 3 | |---->| 4 | |---->| 5 |NULL|
+---+ +-------+ +-------+ +-------+ +-------+ +--------+
^
|
+---+
| |
+---+
indirect
while 循环
while ((*indirect) != entry)
*indirect 将给出第一个节点的地址,因为head 指向第一个节点,并且由于entry 指向第二个节点,循环条件计算为true,然后将执行以下代码:
indirect = &(*indirect)->next;
这将使indirect 指针指向第一个节点的next 指针。内存视图:
entry -+
head |
+---+ +-------+ +-------+ +-------+ +-------+ +--------+
| |---->| 1 | |---->| 2 | |---->| 3 | |---->| 4 | |---->| 5 |NULL|
+---+ +-------+ +-------+ +-------+ +-------+ +--------+
^
|
+---+
| |
+---+
indirect
现在将评估while 循环条件。因为indirect 指针现在指向第一个节点的next,所以*indirect 将给出第二个节点的地址,并且由于entry 指向第二个节点,循环条件计算为false 并且循环退出.
现在将执行以下代码:
*indirect = entry->next;
*indirect 取消对第一个节点的next 的引用,现在它被分配了entry 指针指向的节点的next。内存视图:
entry -+
head |
+---+ +-------+ +-------+ +-------+ +-------+ +--------+
| |---->| 1 | |-- | 2 | |---->| 3 | |---->| 4 | |---->| 5 |NULL|
+---+ +-------+ \ +-------+ +-------+ +-------+ +--------+
*indirect \ /
+------------+
现在第一个节点的next 指向列表中的第三个节点,这样第二个节点就从列表中删除了。
希望这能消除您的所有疑虑。
编辑:
David 在评论中建议添加一些细节 - 为什么&(*indirect)->next 中需要 (..) 括号?
indirect的类型是linked_list **,也就是说它可以保存linked_list *类型的指针的地址。
*indirect 将给出linked_list * 类型的指针,->next 将给出其next 指针。
但我们不能写*indirect->next,因为运算符-> 的优先级高于一元运算符*。因此,*indirect->next 将被解释为*(indirect->next),这在语法上是错误的,因为indirect 是指向指针的指针。
因此我们需要() 围绕*indirect。
另外,&(*indirect)->next 将被解释为&((*indirect)->next),即next 指针的地址。
1)如果您不知道双指针是如何工作的,请查看以下内容:
举个例子:
#include <stdio.h>
int main() {
int a=1, b=2;
int *p = &a;
int **pp = &p;
printf ("1. p : %p\n", (void*)p);
printf ("1. pp : %p\n", (void*)pp);
printf ("1. *p : %d\n", *p);
printf ("1. *pp : %d\n", **pp);
*pp = &b; // this will change the address to which pointer p pointing to
printf ("2. p : %p\n", (void*)p);
printf ("2. pp : %p\n", (void*)pp);
printf ("2. *p : %d\n", *p);
printf ("2. *pp : %d\n", **pp);
return 0;
}
在上面的代码中,在这条语句-*pp = &b;中,你可以看到不直接访问指针p我们可以使用双指针pp来改变它指向的地址,它指向的是指针@ 987654377@,因为取消引用双指针pp 将给出指针p。
它的输出:
1. p : 0x7ffeedf75a38
1. pp : 0x7ffeedf75a28
1. *p : 1
1. *pp : 1
2. p : 0x7ffeedf75a34 <=========== changed
2. pp : 0x7ffeedf75a28
2. *p : 2
2. *pp : 2
内存中的视图是这样的:
//Below in the picture
//100 represents 0x7ffeedf75a38 address
//200 represents 0x7ffeedf75a34 address
//300 represents 0x7ffeedf75a28 address
int *p = &a
p a
+---+ +---+
|100|---->| 1 |
+---+ +---+
int **pp = &p;
pp p a
+---+ +---+ +---+
|300|---->|100|---->| 1 |
+---+ +---+ +---+
*pp = &b;
pp p b
+---+ +---+ +---+
|300|---->|200|---->| 2 |
+---+ +---+ +---+
^^^^^ ^^^^^