问题描述
我试图了解这段代码中双指针的用途及其工作原理。
为什么我们在声明函数中使用 **p
而在函数内部使用 *p
?
void allocate(int** p)
{
*p = (int*)malloc(sizeof(int));
}
int main()
{
int *p = NULL;
allocate(&p);
*p = 42;
}
解决方法
函数的参数 p
具有指向 int
的指针类型,即 int **
。因此,引用 p
是指该类型的对象。
表达式 *p
dereferences p
给你一个类型为 int *
的表达式(也是一个 lvalue)。这与 p
函数中的 main
类型匹配,并且实际上是指该对象。这允许我们在函数 allocate
中修改 p
中 main
的值以包含动态分配的内存块的地址。
要更改在函数p
中的函数main
中声明的原始指针allocate
,您需要通过引用传递它。否则函数将处理原始指针p
的值的副本,更改副本不会影响存储在原始指针中的值。
在 C 中,通过引用传递意味着通过指向对象的指针间接传递对象。因此,取消引用指针,您将可以访问原始对象。
考虑以下演示程序。
#include <stdio.h>
void f( int x )
{
x = 20;
}
int main(void)
{
int x = 10;
printf( "Before calling the function d c = %d\n",x );
f( x );
printf( "After calling the function d c = %d\n",x );
return 0;
}
它的输出是
Before calling the function d c = 10
After calling the function d c = 10
如您所见,原始变量 x
在调用函数 f 后没有改变,因为变量是按值传递给函数的。
现在考虑以下程序。
#include <stdio.h>
void f( int *px )
{
*px = 20;
}
int main(void)
{
int x = 10;
printf( "Before calling the function d c = %d\n",x );
f( &x );
printf( "After calling the function d c = %d\n",x );
return 0;
}
此时程序输出为
Before calling the function d c = 10
After calling the function d c = 20
由于变量 x
是通过引用传递然后取消引用指针
px
*px = 20;
您可以通过指针直接访问原始变量 x
。
所以如果你想改变一个指针本身,那么通过引用传递它意味着传递一个指向该指针的指针,就像在上面的函数中所做的一样,只是现在原始变量p
的类型是{ {1}} 而不是 int *
。
如果你有这样的声明
int
其中 T x;
是某种类型(例如 T
或 int
),然后要通过引用传递变量,您需要使用函数参数表达式,如 int *
。类型为 &x
。如果 T *
等价于 T
类型,那么您需要使用 int *
类型的参数表达式。