如何修改已在C中传递给函数的指针?

如何修改已在C中传递给函数的指针?,c,function,pointers,parameters,pass-by-value,C,Function,Pointers,Parameters,Pass By Value,因此,我有一些代码,类似于下面的代码,用于将结构添加到结构列表中: void barPush(BarList * list,Bar * bar) { // if there is no move to add, then we are done if (bar == NULL) return;//EMPTY_LIST; // allocate space for the new node BarList * newNode = malloc(sizeof(Bar

因此,我有一些代码,类似于下面的代码,用于将结构添加到结构列表中:

void barPush(BarList * list,Bar * bar)
{
    // if there is no move to add, then we are done
    if (bar == NULL) return;//EMPTY_LIST;

    // allocate space for the new node
    BarList * newNode = malloc(sizeof(BarList));

    // assign the right values
    newNode->val = bar;
    newNode->nextBar = list;

    // and set list to be equal to the new head of the list
    list = newNode; // This line works, but list only changes inside of this function
}
这些结构的定义如下:

typedef struct Bar
{
    // this isn't too important
} Bar;

#define EMPTY_LIST NULL

typedef struct BarList
{
    Bar * val;
    struct  BarList * nextBar;
} BarList;
然后在另一个文件中,我执行如下操作:

BarList * l;

l = EMPTY_LIST;
barPush(l,&b1); // b1 and b2 are just Bar's
barPush(l,&b2);

然而,在此之后,l仍然指向空的_列表,而不是在barPush内部创建的修改版本。如果我想修改列表,我是否必须将列表作为指针传递给指针,或者是否需要其他一些黑色咒语

是的,您必须传入指向该指针的指针。C按值传递参数,而不是按引用传递参数。

记住,在C中,所有参数都是按值传递的

您传入一个指向指针的指针,如下所示

int myFunction(int** param1, int** param2) {

// now I can change the ACTUAL pointer - kind of like passing a pointer by reference 

}

如果要执行此操作,需要传入指向指针的指针

void barPush(BarList ** list,Bar * bar)
{
    if (list == NULL) return; // need to pass in the pointer to your pointer to your list.

    // if there is no move to add, then we are done
    if (bar == NULL) return;

    // allocate space for the new node
    BarList * newNode = malloc(sizeof(BarList));

    // assign the right values
    newNode->val = bar;
    newNode->nextBar = *list;

    // and set the contents of the pointer to the pointer to the head of the list 
    // (ie: the pointer the the head of the list) to the new node.
    *list = newNode; 
}
然后像这样使用它:

BarList * l;

l = EMPTY_LIST;
barPush(&l,&b1); // b1 and b2 are just Bar's
barPush(&l,&b2);
Jonathan Leffler建议在评论中返回新的名单负责人:

BarList *barPush(BarList *list,Bar *bar)
{
    // if there is no move to add, then we are done - return unmodified list.
    if (bar == NULL) return list;  

    // allocate space for the new node
    BarList * newNode = malloc(sizeof(BarList));

    // assign the right values
    newNode->val = bar;
    newNode->nextBar = list;

    // return the new head of the list.
    return newNode; 
}
用法变为:

BarList * l;

l = EMPTY_LIST;
l = barPush(l,&b1); // b1 and b2 are just Bar's
l = barPush(l,&b2);

这是一个经典问题。返回分配的节点或使用指针的指针。在C语言中,应该将指向X的指针传递给希望修改X的函数。在这种情况下,由于您希望修改指针,因此应该将指针传递给指针。

一般答案:将指针传递给要更改的对象


在本例中,它将是指向您要更改的指针的指针。

在另一个函数中修改指针需要一个称为多重间接寻址的概念,我将在后面解释,给定@geofftnz的扰流板解决方案使用多重间接寻址。我想做的是尽力解释C语言中的多重间接寻址

考虑以下两个程序,我将浏览代码

以下程序不使用多个间接寻址,因此失败

有错误的程序:

// filename: noIndirection.c
#include <stdio.h>
#include <stdlib.h>

void allocater(int *ptrTempAllctr)
{
    ptrTempAllctr = malloc(sizeof(int));
    if (ptrTempAllctr == NULL) {
        perror("in allocater() memory allocation error");
        exit(EXIT_FAILURE);
    }
}

int main() 
{
    int *ptrMain = NULL;
    allocater(ptrMain);
    if (ptrMain == NULL) {
        printf("ptrMain is points to NULL\n");
        return 1;
    }
    //free(ptrMain);  // we don't have to free because it will be invalid free.
    return 0;
}
我们使用(
&
)运算符的地址分配它们

多个间接指针类型变量的作用是,允许我们 指向指针变量本身的指针,用于修复上述程序。 这允许我们将
ptrMain的地址传递给
allocator()
使用此呼叫

分配器(&ptrMain)

因此,上面的程序
noIndirection.c
不允许我们这样做,请参阅程序
withIndirection.c
以实现此多重间接寻址

我们需要指向int指针(
int**ptrMain
)的指针作为
allocator()
函数的函数参数,在这种情况下,可以解决上述错误程序(noIndirection.c)

这在以下程序中使用

下面的程序使用多重间接来解决上一个程序中的错误

// filename: withIndirection.c
#include <stdio.h>
#include <stdlib.h>

void trueAllocater(int **ptrTrueAllocater)
{
    *ptrTrueAllocater = (int *) malloc(sizeof(int));
    if (ptrTrueAllocater == NULL) {
        perror("in trueAllocater() memory allocation error");
        exit(EXIT_FAILURE);
    }
}

int main(void) 
{
    int *ptrMain = NULL;
    trueAllocater(&ptrMain);
    if (ptrMain == NULL) {
        printf("memory not allocated\n");
        return EXIT_FAILURE;
    }

    printf("memory allocated and assigned to ptrMain");
    printf(" from trueAllocater\n");

    free(ptrMain);
    return EXIT_SUCCESS;
}
//文件名:withIndirection.c
#包括
#包括
void trueallocator(int**ptrtruelocator)
{
*ptrTrueAllocater=(int*)malloc(sizeof(int));
if(ptrTrueAllocater==NULL){
perror(“在TrueAllocator()内存分配错误中”);
退出(退出失败);
}
}
内部主(空)
{
int*ptrMain=NULL;
trueallocator(&ptrMain);
if(ptrMain==NULL){
printf(“未分配内存”);
返回退出失败;
}
printf(“分配给ptrMain的内存”);
printf(“来自TrueAllocator\n”);
免费(ptrMain);
返回退出成功;
}
请参阅程序
with indirection.c
,以了解今后的参考信息

为了解决我们的问题,我们需要将指针变量
ptrMain
trueallocator(&ptrMain);
)的地址传递给trueallocator,以便更改
ptrMain
后面需要在
trueallocator()或其他函数中指向的位置,
为此,函数需要接受具有正确间接级别的间接指针,
这是为了在参数声明中添加另一个*以达到我目前对传递的变量的理解

通过这种方式,我们需要将
trueallocator()
函数参数设置为
int**
from
int*
in
with indirection.c
而不是
noIndirection.c
因此,间接层将被统计

调用方的参数变量
ptrMain
的实际地址传递给函数时。中的temprary
ptrTrueAllocater
参数变量 函数指向指针变量
ptrMain
在调用者中的地址(
main
)函数不是指针变量
ptrMain
(在程序中为
NULL
)在函数中指向的地址(
main

如果我们取消引用
ptrRueAllocater
变量,将显示
ptrMain
指向的地址,因为
ptrRueAllocater
临时变量指向调用者(
main
ptrMain
变量本身,而不是它的内容

取消引用的
ptrRueAllocater
变量的内容将是调用者(
main
)的变量(
ptrMain
)指向的数据的地址, 因此,我们必须进行一次额外的解引用以获得最终数据

因此,我们必须取消引用一次,以获得它所指向的
ptrMain
的地址,从而更改
ptrMain
需要指向和取消引用的位置 两次以获取
ptrMain
指向的实际数据,该值为
NULL

@PaulWicks您打算更改,因此您必须取消引用一次,以分配或更改其指向的位置

使用指针进行多个间接寻址的目的是创建多维数组并传递需要指向某个对象的指针参数

我们需要根据需要操作的类型更改变量,如下所示

声明中每增加一个*都会增加指针间接寻址级别 每次取消引用都会降低指针的间接寻址级别,从而接近数据

我们可以
// filename: withIndirection.c
#include <stdio.h>
#include <stdlib.h>

void trueAllocater(int **ptrTrueAllocater)
{
    *ptrTrueAllocater = (int *) malloc(sizeof(int));
    if (ptrTrueAllocater == NULL) {
        perror("in trueAllocater() memory allocation error");
        exit(EXIT_FAILURE);
    }
}

int main(void) 
{
    int *ptrMain = NULL;
    trueAllocater(&ptrMain);
    if (ptrMain == NULL) {
        printf("memory not allocated\n");
        return EXIT_FAILURE;
    }

    printf("memory allocated and assigned to ptrMain");
    printf(" from trueAllocater\n");

    free(ptrMain);
    return EXIT_SUCCESS;
}