为什么我们需要将地址值传递给接受双指针的参数?

问题描述

#include <stdlib.h>
int malloc2(int **a) {
  *a = malloc(sizeof (int));
return 0;

}
int main() {
  int* b = NULL;
  malloc2(&b);
}

如果一个参数只接受双指针,它如何接受地址值?

解决方法

如果不通过指向它的指针通过引用传递指针b,则该函数将处理指针值的副本

在函数内更改副本不会影响原始指针。

结果是该函数产生了内存泄漏。

要更改原始指针 b,该函数需要直接访问该指针。可以通过解引用指向指针(对象)b的指针来实现。

比较这两个演示程序。

#include <stdio.h>

void f( int *p )
{
    ++p;
    printf( "Within the function f p = %p\n",( void * )p );
}

int main(void) 
{
    int x = 10;
    int *p = &x;
    
    printf( "Before calling f p = %p\n",( void * )p );
    
    f( p );
    
    printf( "After  calling f p = %p\n",( void * )p );

    return 0;
}

程序输出为

Before calling f p = 0x7ffc3a940cbc
Within the function f p = 0x7ffc3a940cc0
After  calling f p = 0x7ffc3a940cbc

如您所见,在调用函数 p 后,main 中声明的指针 f 没有改变。

另一个程序

#include <stdio.h>

void f( int **p )
{
    ++*p;
    printf( "Within the function f p = %p\n",( void * )p );
    
    f( &p );
    
    printf( "After  calling f p = %p\n",( void * )p );

    return 0;
}

程序输出为

Before calling f p = 0x7ffe011131ec
Within the function f p = 0x7ffe011131f0
After  calling f p = 0x7ffe011131f0

现在可以看到 main 中声明的指针 p 在调用函数 f 后发生了变化,因为它是通过指向它的指针通过引用传递给函数的。取消对指针的引用,函数可以直接访问在 main 中声明的指针 p

如果一个参数只接受双指针,它怎么能接受一个 地址值

每个值都根据其类型进行解释。此表达式 &b 的值具有类型 int **。并且函数参数也有 int ** 类型。

您可以想象函数定义及其调用方式如下

int main() {
  int* b = NULL;
  malloc2(&b);
}
//...
int malloc2( /* int **a */ ) {
  int **a = &b; 
  *a = malloc(sizeof (int));
return 0;
}

即函数参数a由表达式&b的值初始化。

或者更简单的例子

int main( void )
{
    int x = 10;
    int *b = &x;
    int **a = &b;
}
,

该函数接受单个 int ** 参数,即 pointer-to-pointer-to-int

b 中的变量 main 的类型为 int *,即 pointer-to-int。如果你然后取 b 的地址,你现在有一个 pointer-to-pointer-to-int,即匹配函数参数的 int **