这可能是一个愚蠢的问题,但我真的很想知道为什么会这样。尝试为链接列表创建追加函数时,为何此单指针解决方案不起作用,但是当使用双指针时却起作用?
单指针:
void append(node *head, int value){
node *current = head;
node *new = malloc(sizeof(node));
if (new == NULL){
printf("couldn't allocate memory");
return;
}
new->value = value;
new->next = NULL;
if (head == NULL){
head = new;
return;
}
while (current->next != NULL)
current = current->next;
current->next = new;
return;}
双指针:
void append(node **head, int value){
node *current = *head;
node *new = malloc(sizeof(node));
if (new == NULL){
printf("couldn't allocate memory");
return;}
new->value = value;
new->next = NULL;
if (*head == NULL){
*head = new;
return;
}
while (current->next != NULL)
current = current->next;
current->next = new;
return;}
答案 0 :(得分:2)
使用一个参数调用函数时,会在堆栈上创建该参数的副本。因此在某种程度上,它们与局部变量非常相似。
在单指针情况下,语句head = new;
实际上只是导致对参数head
的更改,并且此更改不会传播回传递给的实际头。
在双指针情况下,您将获得head
的地址,可以通过执行*head = new;
来对其进行更改。
答案 1 :(得分:1)
想象一下,您的记忆力在不断增强
------------- ------------
| head 0x10 | -> | 0x20 |
------------- ------------
0x10是head的地址,而不是它指向的地址,它指向的地址是0x20。
如果仅用一个指针调用append
,它将把head值复制到函数append
的本地地址
这样,对于append
,头可能是:
------------- ------------
| head 0x25 | -> | 0x20 |
------------- ------------
因此,标头的新地址为 0x25 ,指向 0x20
如果您使函数内的head
指向另一个地址,例如:
------------- ------------
| head 0x25 | -> | 0x30 |
------------- ------------
只有函数内部的head
会指向不同的地址,在调用方函数中它将仍然是:
------------- ------------
| head 0x10 | -> | 0x20 |
------------- ------------
因为要按值传递指针,所以该函数正在复制指针。 为了解决这个问题,您需要将一个指针传递给一个指针,因此您的变量将是:
local
------------- ------------- ------------
| head 0x25 | -> | head 0x10 | -> | 0x20 |
------------- ------------- ------------
现在您有了一个指向调用者指针的指针,因此您可以对其指向的位置进行更改,并将其反映在调用者头上。
例如
local
------------- ------------- ------------
| head 0x25 | -> | head 0x10 | -> | 0x30 |
------------- ------------- ------------