[英]C Linked List pointer understanding
I'm trying to understand how C linked list pointer works.我试图了解 C 链表指针的工作原理。 I understand that a pointer to a variable is a "link" to an address memory, and that a pointer to a pointer is, sometimes, a reference to a pointer itself.
我知道指向变量的指针是指向地址存储器的“链接”,而指向指针的指针有时是对指针本身的引用。
What concerns me is how could, for example, a node reference modify the original list value, but not the list itself.我担心的是,例如,节点引用如何修改原始列表值,而不是列表本身。
I'll explain myself better:我会更好地解释自己:
void insertNode(struct node** head, int value) {
struct node* new = malloc(sizeof(struct node*));
struct node* ref = (*head); //this is a reference. -> same address.
//base case
if((*head) == NULL) {
//do things
} else { // not null
while(ref->next != null) {
ref = ref->next; //THIS: how can this not modify the head itself?
}
//null spot found, set up node
new->value = 10; //some int here
new->next = NULL;
ref->next = new; //Instead, how can this modify the head? and why?
}
}
here's a little snippets of code, and my question is: Yes, i'm holding a reference to head through ref .这是一些代码片段,我的问题是:是的,我正在持有一个参考来通过ref 。 But why
但为什么
ref = ref->next;
only modify ref itself, while只修改 ref 本身,而
ref->next = new
modify also the head?还修改头?
through GDB i saw that both, at the beginning, share the same address memory, but ref only modify the referenced list on the new insert.通过 GDB,我看到两者在开始时共享相同的地址内存,但 ref 仅修改新插入的引用列表。
Can someone explain it?有人可以解释一下吗?
ref
is just a pointer; ref
只是一个指针; modifying ref
will not modify what is pointed by ref
.修改
ref
不会修改ref
指向的内容。
The while
loop is actually just looking for the last element of the list. while
循环实际上只是在寻找列表的最后一个元素。 After the while
loop , ref
will simply point to the last element of the list.在
while
循环之后, ref
将简单地指向列表的最后一个元素。
First "mystery" line:第一个“神秘”线:
ref = ref->next; //THIS: how can this not modify the head itself?
Here we just read ref->next
, so the head cannot be modified.这里我们只读取了
ref->next
,所以 head 不能修改。
Second "mystery" line:第二个“神秘”线:
ref->next = new; //Instead, how can this modify the head? and why?
Here we modify what is pointed by ref
.这里我们修改了
ref
指向的内容。 At this line ref
points either to the last element of the list, or it points the head (which is also the last element of the list if there is only one element in the list, or which is the newly created head (to be done in //do things
) if the list was empty.在这一行,
ref
要么指向列表的最后一个元素,要么指向头部(如果列表中只有一个元素,它也是列表的最后一个元素,或者是新创建的头部(待完成) in //do things
) 如果列表为空。
Maybe some pictures will help.也许一些图片会有所帮助。
Before calling insertNode
, you have a sequence of nodes linked like so:在调用
insertNode
之前,您有一个链接的节点序列,如下所示:
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
You have a pointer (call it h
) that points to the first element of the list:您有一个指向列表第一个元素的指针(称为
h
):
+---+
| h |
+---+
|
V
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
When you call insertNode
, you pass a pointer to h
in as a parameter, which we call head
:当你调用
insertNode
,你传递一个指向h
in的指针作为参数,我们称之为head
:
+------+
| head |
+------+
|
V
+---+
| h |
+---+
|
V
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
You create a pointer variable named ref
that takes the value of *head
( h
);您创建了一个名为
ref
的指针变量,该变量采用*head
( h
) 的值; IOW, ref
winds up pointing to the first element of the list: IOW,
ref
最终指向列表的第一个元素:
+------+ +-----+
| head | | ref |
+------+ +-----+
| |
V |
+---+ |
| h | |
+---+ |
| +----+
V V
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
Then you create another node on the heap, and assign that pointer to a local variable named new
:然后在堆上创建另一个节点,并将该指针分配给名为
new
的局部变量:
+------+ +-----+ +-----+ +-------+------+
| head | | ref | | new | ---> | value | next |
+------+ +-----+ +-----+ +-------+------+
| |
V |
+---+ |
| h | |
+---+ |
| +----+
V V
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
So, the thing to notice is that while ref
and *head
( h
) have the same value (the address of the first node in the list), they are different objects.因此,需要注意的是,虽然
ref
和*head
( h
) 具有相同的值(列表中第一个节点的地址),但它们是不同的对象。 Thus, anything that changes the value of ref
does not affect either head
or h
.因此,任何改变
ref
值的事情都不会影响head
或h
。
So, if we execute this loop所以,如果我们执行这个循环
while(ref->next != null) {
ref = ref->next;
the result of the first iteration is第一次迭代的结果是
+------+ +-----+ +-----+ +-------+------+
| head | | ref | | new | ---> | value | next |
+------+ +-----+ +-----+ +-------+------+
| |
V |
+---+ |
| h | |
+---+ |
| +------------+
V V
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
After another iteration we get经过另一次迭代,我们得到
+------+ +-----+ +-----+ +-------+------+
| head | | ref | | new | ---> | value | next |
+------+ +-----+ +-----+ +-------+------+
| |
V |
+---+ |
| h | |
+---+ |
| +----------------------------------+
V V
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
At this point, ref->next
is NULL
, so the loop exits.此时,
ref->next
为NULL
,因此循环退出。
We then assign values to new->value
and new->next
, such that new->next
is NULL
:然后我们将值分配给
new->value
和new->next
,这样new->next
是NULL
:
+------+ +-----+ +-----+ +-------+------+
| head | | ref | | new | ---> | value | next | ---|||
+------+ +-----+ +-----+ +-------+------+
| |
V |
+---+ |
| h | |
+---+ |
| +----------------------------------+
V V
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
Finally, we set ref->next
to the value of new
, thus adding the node new
points to to the end of the list:最后,我们将
ref->next
设置为new
的值,从而将节点new
指向列表的末尾:
+------+ +-----+ +-----+ +-------+------+
| head | | ref | | new | ---> | value | next | ---|||
+------+ +-----+ +-----+ +-------+------+
| | ^
V | |
+---+ | +-------------------------------+
| h | | |
+---+ | |
| +----------------------------------+ |
V V |
+-------+------+ +-------+------+ +-------+------+ |
| value | next | ---> | value | next | ---> | value | next | ---+
+-------+------+ +-------+------+ +-------+------+
Note that ref->next
isn't pointing to the variable new
, it's pointing to the thing that new
points to.需要注意的是
ref->next
没有指向变new
,它所指向的东西, new
点。
So, that's why updating ref
does not affect head
(or *head
( h
)).所以,这就是为什么更新
ref
不会影响head
(或*head
( h
))。 The base case, where the list is empty, will end up writing to *head
( h
), setting it to point to a new node allocated from the heap.列表为空的基本情况将最终写入
*head
( h
),将其设置为指向从堆分配的新节点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.