为什么以及何时需要双指针?

时间:2013-11-29 08:54:47

标签: c pointers linked-list

我一生中大部分时间都是系统管理员,但最近决定练习一些我的开发知识并尝试一个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的任何东西),我注意到插入函数末尾的打印似乎有效。所以试图在网上寻找答案,我找不到任何东西,显而易见但我发现大多数列表实现都会有双指针。我改变了我的功能以使用双指针,然后它突然开始工作。有人可以帮助我理解这里发生了什么,因为我知道指针管理是一个重要的概念,我想我理解指针是什么以及它与内存的关系,但我不认为我明白为什么单个指针不会被改变,而双指针确实如此。

谢谢!

3 个答案:

答案 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