如何修改已传递给 C 函数的指针?
因此,我有一些代码,类似于下面的代码,将结构添加到结构列表中:
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 仍然指向到 EMPTY_LIST,而不是 barPush 内部创建的修改版本。如果我想修改它,我是否必须将列表作为指向指针的指针传递,或者是否需要其他一些黑暗咒语?
So, I have some code, kind of like the following, to add a struct to a list of structs:
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
}
These structures are defined as follows:
typedef struct Bar
{
// this isn't too important
} Bar;
#define EMPTY_LIST NULL
typedef struct BarList
{
Bar * val;
struct BarList * nextBar;
} BarList;
and then in another file I do something like the following:
BarList * l;
l = EMPTY_LIST;
barPush(l,&b1); // b1 and b2 are just Bar's
barPush(l,&b2);
However, after this, l still points to EMPTY_LIST, not the modified version created inside of barPush. Do I have to pass list in as a pointer to a pointer if I want to modify it, or is there some other dark incantation required?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
修改另一个函数中的指针需要一个称为多重间接的概念,我将在稍后解释它,鉴于@geofftnz使用多重间接,剧透解决方案。我想做的是尽力解释 C 中的多重间接。
考虑以下两个程序,我将逐步介绍代码。
以下程序未使用多重间接寻址,因此失败。
有错误的程序:
考虑上面的程序(
noIndirection.c
),它有一个变量ptrMain
,它是一个指向 int 的指针。如果它被传递给一个函数,在函数作用域(主体)中会创建一个临时指针变量,因为函数的参数是临时变量,当它们超出作用域时它们会被删除。
临时指针变量
ptrTempAllctr
(它是一个参数)将指向调用者 (main
) 函数的变量ptrMain
(它指向NULL
) 在作为参数传递给函数时指向。如果我们使用
malloc()
或将另一个指针分配给临时变量ptrTempAllctr
,那么它将指向它,但caller(main
) 作为参数传递给函数allocater()
的函数仍然指向函数调用之前所指向的相同数据(即NULL
)。当被调用的 (
allocater()
) 函数超出范围时,临时指针变量将从堆栈中弹出,并且内存未分配,最终导致内存泄漏。为了绕过这个限制,我们需要使用多重间接。
多重间接:
我们使用address-of(
&
)运算符来分配它们。多个间接指针类型变量的作用是,允许我们做的是
指向指针变量本身的指针,用于修复上述程序。
这允许我们将
ptrMain
的地址传递给allocater()
使用此调用
allocater(&ptrMain);
因此上述程序
noIndirection.c
不允许我们这样做,请参阅程序withIndirection.c 来实现这种多重间接寻址。
在这种情况下,我们需要指向 int 指针(
int **ptrMain
)的指针作为allocater()
函数的函数参数来解决上述错误程序(noIndirection.c)。这在下面的程序中被使用。
下面的程序使用多重间接来解决前面程序中的错误。
从现在开始,请参阅程序
withIndirection.c
以供参考。为了解决我们的问题,我们需要将指针变量
ptrMain
(trueAllocater(&ptrMain);
) 的地址传递给 trueAllocater,以便更改ptrMain
稍后需要在trueAllocater()
或其他函数中指向它,为此,函数需要接受具有正确间接级别的间接指针,
这是根据我当前对传递的变量的理解,在参数声明中添加另一个 * 。
也就是说,我们需要将
trueAllocater()
函数参数设置为withIndirection.c
int * 的int **
> 与noIndirection.c
相反因此间接级别将得到满足。
当调用者的参数变量
ptrMain
的实际地址被传递给函数时。中的临时ptrTrueAllocator
参数变量函数指向调用者(
main
)函数中指针变量ptrMain
的地址,而不是指针变量ptrMain
(这是NULL)指向函数(
main
)中。如果我们取消引用
ptrTrueAllocater
变量,则ptrMain
指向的地址将被显示,因为ptrTrueAllocater
临时变量指向调用者(main
)ptrMain
变量本身不是它的内容。解引用的
ptrTrueAllocater
变量的内容将是调用者 (main
) 的变量 (ptrMain
) 所指向的数据的地址,因此我们必须进行额外的取消引用才能获得最终数据。
因此我们必须取消引用一次才能获取它指向的 ptrMain 的地址,以便更改需要指向的位置并取消引用
两次以获取
ptrMain
指向的实际数据,该数据为NULL
。@PaulWicks,您打算更改,因此您必须取消引用一次才能分配或更改其指向的位置。
使用指针进行多重间接寻址的目的是创建多维数组并传递需要指向某些内容的指针参数。
我们需要根据我们必须操作的类型来更改变量,如下所示,
声明中每次添加 * 都会增加指针间接级别
每次取消引用都会降低指针间接级别,即接近数据。
我们可以通过将地址返回给分配给所需指针变量的调用函数来解决这个问题。
是的,我们可以使用这种多重间接变量语法来创建一个或
多维数组。如果初学者花时间的话,一开始这会让他们感到困惑
阅读大量代码,他们将能够找到它们之间的区别。
如果我错了,请纠正我,请反馈并让我知道是什么
多重间接指针的其他用途。
为我糟糕的英语道歉。
这些资源帮助我理解多重间接。
https://boredzo.org/pointers/#function_pointers
https://cseweb.ucsd.edu/~ricko/rt_lt.rule.html< /a>
Modifying a pointer in another function requires a concept called multiple indirection, I will explain it in later, spoiler solution given @geofftnz uses multiple indirection. What I am trying to do is try my best to explain multiple indirection in C.
Consider the following two programs, I will walk through the code.
The following program does not use multiple indirection, so it fails.
program with error:
consider the above program(
noIndirection.c
), which has a variableptrMain
it is a pointer points to an int.If it was passed to a function, in the function scope(body) a temporary pointer variable is created because arguments of the function are temporary variables, they get deleted when they go out of scope.
The temporary pointer variable
ptrTempAllctr
(which is a argument) will point to what ever the caller(main
) function's variableptrMain
(which is pointing toNULL
) pointed when it was passed as argument to the function.If we use
malloc()
or assign another pointer to the temporary variableptrTempAllctr
then it will point to it but the pointer variable in caller(main
) function that was passed as argument to the to functionallocater()
still points to the same data(which isNULL
) which it was pointed before the function call.When the called (
allocater()
) function goes out of scope the temporary pointer variable is popped from stack and the memory left unallocated we end up memory leak.To bypass this limitation we need use multiple indirection.
MULTIPLE INDIRECTION:
and we assign them using address-of(
&
) operator.what multiple indirection pointer type variables does is, allows us to make is
a pointer to a pointer variable itself for fixing the above program.
This allows us to pass the address of the
ptrMain
toallocater()
using this call
allocater(&ptrMain);
thus the above program
noIndirection.c
doesn't allow us do this, see the programwithIndirection.c
to implement this multiple indirection.We need pointer to int pointer(
int **ptrMain
) as function argument forallocater()
function in this case to solve the above buggy program(noIndirection.c).This was used in the following program.
The following program uses multiple indirection to solve the bug in previous program.
see the program
withIndirection.c
for reference from now.To solve our problem we need pass the address of the pointer variable
ptrMain
(trueAllocater(&ptrMain);
) to the trueAllocater, in-order to changeptrMain
where it needs to be pointing later on intrueAllocater()
or another function,to do this the function needs to accept indirection pointer with correct level of indirection,
which is to add another * added to the argument declaration to my current understanding for the variables that are passed.
By means we need to have the
trueAllocater()
function argument asint **
fromint *
inwithIndirection.c
as opposed tonoIndirection.c
so the indirection level will be statisfied.
When the address of the caller's argument variable
ptrMain
's actual address was passed to the function. the tempraryptrTrueAllocater
argument variable infunction is pointing to the address of pointer variable
ptrMain
's address in caller(main
) function not what pointer variableptrMain
(which isNULL
in the program) points to in function(main
).If we dereference the
ptrTrueAllocater
variable the address whichptrMain
points to will be revealed because theptrTrueAllocater
temporary variable is pointing to the caller(main
)ptrMain
variable itself not it contents.The contents of the dereferenced
ptrTrueAllocater
variable will be the address of the data which was pointed by the caller(main
)'s variable(ptrMain
),so we have to do one additional dereference to get the final data.
so we have to dereference once to get the address of the
ptrMain
which it points in-order to change the whereptrMain
needs to be pointed and dereferencetwice to get the actual data pointed by the
ptrMain
which isNULL
.@PaulWicks you intented to change so you have to dereference once to allocate or change where its pointing.
The intent of multiple indirecting using pointers is to create multi-dimensional array and passing pointer arguments that need to be pointed to something.
We need to change the variable according to the types we have to manipulate like the following,
every addition of * in declaration will increase pointer indirection level
and every dereference will decrease the pointer indirection level that is will get close to data.
We can solve this problem by returning the address to the caller function assigning to the required pointer variable.
yes, we can use this multi indirection variable syntax for creating one or
multi dimensional arrays. This will confuse beginners at first, if they put time to
read lots of code they'll able to find the difference between them.
Please correct me if I am wrong, please give feedback and let me know what are
the other uses of multiple indirection pointers.
apologies for my bad english.
these are the resources helped me to understand multiple indirections.
https://boredzo.org/pointers/#function_pointers
https://cseweb.ucsd.edu/~ricko/rt_lt.rule.html
如果你想这样做,你需要传入一个指向指针的指针。
然后像这样使用它:
Jonathan Leffler 建议在评论中返回列表的新头:
用法变为:
You need to pass in a pointer to a pointer if you want to do this.
Then use it like this:
Jonathan Leffler suggested returning the new head of the list in the comments:
Usage becomes:
通用答案:传递一个指向您想要更改的内容的指针。
在这种情况下,它将是一个指向您要更改的指针的指针。
Generic answer: Pass a pointer to the thing you want to change.
In this case, it would be a pointer to the pointer you want to change.
请记住,在 C 中,一切都是按值传递的。
您传递一个指针到一个指针,就像这样
Remember, in C, EVERYTHING is passed by value.
You pass in a pointer to a pointer, like this
这是一个经典问题。要么返回分配的节点,要么使用指针的指针。在 C 中,您应该将指向 X 的指针传递给您想要修改 X 的函数。在这种情况下,由于您想要修改指针,因此应该将指针传递给指针。
This is a classic problem. Either return the allocated node or use a pointer of pointer. In C, you should pass a pointer to a X to a function where you want your X to be modified. In this case, since you want a pointer to be modified, you ought to pass a pointer to a pointer.
是的,你必须传入一个指向指针的指针。 C 按值传递参数,而不是按引用传递参数。
Yes, you have to pass in a pointer to the pointer. C passes arguments by value, not by reference.