我一生中大部分时间都是系统管理员,但最近决定练习一些我的开发知识并尝试一个devop位置。我一直在练习一些C和Python技能,并编写了一些代码,用于在链表中插入一个数字。
void list_insert(struct list *h, int d)
{
struct list *elem = malloc(sizeof(struct list));
elem->data = d;
elem->next = NULL;
if (!h) {
h = elem;
} else {
elem->next = h;
h = elem;
}
}
我注意到这个函数似乎没有改变变量h的外部视图(即传递给list_insert的任何东西),我注意到插入函数末尾的打印似乎有效。所以试图在网上寻找答案,我找不到任何东西,显而易见但我发现大多数列表实现都会有双指针。我改变了我的功能以使用双指针,然后它突然开始工作。有人可以帮助我理解这里发生了什么,因为我知道指针管理是一个重要的概念,我想我理解指针是什么以及它与内存的关系,但我不认为我明白为什么单个指针不会被改变,而双指针确实如此。
谢谢!
答案 0 :(得分:6)
在C中,函数的参数由值传递。甚至指针都是通过值传递的。
例如:
#include<malloc.h>
#include<stdio.h>
int allocatingMemory(int* ptr)
{
ptr = malloc(sizeof(int));
if(ptr==NULL)
return -1;
else
return 0;
}// We are not returning the pointer to allocated memory
int main(void)
{
int* ptr;
int allocated = allocatingMemory(ptr);
if(allocated == 0)
{
*ptr = 999;// Boom!!!
free(ptr);
}
return 0;
}
要解决此问题,我们使用
int allocatingMemory(int** ptr)
{
*ptr = malloc(sizeof(int));
if(*ptr == NULL)
return -1;
else
return 0;
}
int main(void)
{
int* ptr;
int isAllocated = allocatingMemory(&ptr);
if(isAllocated == 0)
{
*ptr = 999;
free(ptr);
}
return 0;
}
如果您正在使用linked list
并且例如说,您想要修改头部。您将向pointer to pointer
传递head node
(请注意,它不会被称为双指针)。
答案 1 :(得分:4)
要在调用者的上下文中更改内存,函数需要有一个指向该内存的指针。
如果函数的调用者在变量中有一个空列表,并且在该列表上插入如下:
struct list *numbers = NULL;
list_insert(numbers, 4711);
然后当然在list_insert()
里面我们只有NULL指针,所以我们不能在调用者的上下文中改变变量numbers
的值。
另一方面,如果给出一个指向变量的指针,我们可以改变变量。
那就是说,(在我看来)返回列表的新头部更加清晰,即使函数的签名为struct list * list_insert(struct list *head, int x);
。
答案 2 :(得分:1)
h实际上是原始指针的副本,因此您的原始指针不会被修改。这就是你应该使用双指针的原因。
在SO上有很多与此相关的问题。例如Using single versus double pointers in Linked lists implemented in C