假设我们希望通过一个函数修改指针p所指的内容,那么我们通常需要是传递p的地址。
这样函数的签名通常需要为 void** p
下面代码:
void fail(int* arr,int * d){
printf("param addr:%p param value:%p \n",&d,d);
d = &arr[0];
}
void success(int* arr, int** d){
printf("param addr:%p param value:%p \n",&d,d);
*d = &arr[0];
}
int main(int argc, const char * argv[]) {
using namespace std;
int arr[2]={4,5};
int value = 10;
int* p = &value;
printf("value addr:%p, value:%d\n",&value,value);
//指针的地址,指针值,指针所指的值
printf("p addr:%p p:%p value:%d\n",&p,p,*p);
fail(arr,p);//无法修改p所指向的值
printf("p addr:%p p:%p value:%d\n",&p,p,*p);
success(arr,&p);//可以修改
printf("p addr:%p p:%p value:%d\n",&p,p,*p);
return 0;
}
输出结果
value addr:0xf7ac, value:10
p addr:0xf7a0 p:0xf7ac value:10
param addr:0xf770 param value:0xf7ac
p addr:0xf7a0 p:0xf7ac value:10
param addr:0xf770 param value:0xf7a0
p addr:0xf7a0 p:0xf7c0 value:4
如果希望d的结果执行arr[0]的第一个元素,函数f无法达到要求,f2可以。
对于fail函数,进入函数后,系统给d分配了空间,其地址为0xf770,参数传递时,0xf770上所存储的值修改为p的值,然后执行d=&arr[0],这样又修改oxf770上的值为&arr[0],而p的值根本没有影响。
显然不得到p的地址,即p的实际存储空间,如何修改得了p呢。所以必须使用p,即指向指针的指针来保存p的地址并传递给函数。
success传得p的地址,此时0xf770上存储的值为p的地址。通过d可以修改p存储的值,d=arr[0]成功修改了p的值。
C语言中地址仅仅代表存储位置,使用指针p表示地址,*p对地址内容查询和修改,结合sizeof获得地址内容大小。只需要牢固掌握这一点就可以比较好的理解指针的运用。
C语言中函数本质都是传值,只是当我们传得是地址值时,就可以通过地址值修改地址的内容。
而C语言中指针的值本质上是地址值,但是修改指针的值就必须传指针的本身地址值,而不是指针的值。
网友评论