在传递一级指针时,只有对指针所指向的内存变量做操作才是有效的;
在传递二级指针时,只有对指针的指向做改变才是有效的;
下面做简单的分析:
在函数传递参数时,编译器总会为每个函数参数制作一个副本,即拷贝;
例如:
void fun(int *p),指针参数p的副本为_p,编译器使_p=p,_p和p指向相同的内存空间,如果在函数内修改了_p所指向的内容,就会导致p的内容也做相应的改变;
但如果在函数内_p申请了新的内存空间或者指向其他内存空间,则_p指向了新的内存空间,而p依旧指向原来的内存空间,因此函数返回后p还是原来的p。
这样的话,不但没有实现功能,反而每次都申请新的内存空间,而又得不到释放,因为没有将该内存空间的地址传递出来,容易造成内存泄露。
void fun(int **p),如果函数参数是指针的地址,则可以通过该参数p将新分配或新指向的内存地址传递出来,这样就实现了有效的指针操作。
#include<stdio.h>
#include<malloc.h>
typedef struct list {
int data;
}list_t, *list_pt;
void pp(list_t ** x) {
// 此时 x是&tmp拷贝,直接输出x的值为tmp的地址
printf("&x=%d\n", &x); // 打印x的地址,与tmp的地址不一样
printf("x=%d\n", x); // 输出x的值为tmp的地址
printf("*x=%d\n", *x); // 输出的为tmp的值,也就是结构体内存的首地址
printf("**x=%d\n", **x); // 输出的为结构体的首地址为起始的int长度的值
int tmp1 = 5;
x = &tmp1; //此时x指向的值是新的tmp1 ,当此处x为*x时,即为tmp的指向变为了tmp1的地址
printf("%d\n",*x);
}
int main()
{
list_pt tmp = NULL;
tmp = (list_pt)malloc(sizeof(list_t));
tmp->data = 10;
printf("tmp=%d\n", tmp);
printf("&tmp=%d\n", &tmp); //打印tmp指针的地址
pp(&tmp); //传入tmp的地址
printf("%d\n", *tmp);
return 0;
}