浅析指针的指针

int a = 12;
int *b = &a;
int **c = &b;

代码图析如下,c为指针的指针。
这里写图片描述

指针b中存放的是a的地址,指针c中存放的是指针b的地址
例:


 int i = 5,j = 6;
 int *ip1 = &i,*ip2 = &j;
 int **ipp = &ip1;

输出结果:

&i:0x3a73ea1c,
&j:0x3a73ea18,
ip1:0x3a73ea1c,
&ip1:0x3a73ea10,
ipp:0x3a73ea10,
*ipp:0x3a73ea1c

图析:
这里写图片描述
上例中,我们加上一行代码 *ipp = ip2,你觉得打印结果如何?

 int i = 5,j = 6;
 int *ip1 = &i,*ip2 = &j;
 int **ipp = &ip1;
 *ipp = ip2

输出结果:

&i:0x2267bf5c,
&j:0x2267bf58,
ip1:0x2267bf58,
&ip1:0x2267bf50,
ipp:0x2267bf50,
*ipp:0x2267bf58

图析:
这里写图片描述
为什么在第二幅图里,ipp 还是指向 ip1 而不是 ip2?

注意 :指针里面存放的是地址。
当你这么写时 *ipp = ip2,实际上是把 ipp 存的地址所对应的对象,也就是 ip1 取到,然后把 ip2 存的值赋值给 ip1,也就是 j 的地址。

看个经典案例(error):

void GetMemory(char *p,int num)
{
    p=(char*)malloc(sizeof(char)*num);      
}
void main()
{
    char *str=NULL;
    GetMemory(str,100);                           
    strcpy(str,"hello");
}

结构是编译能通过,却不能运行

先说一下指针作为函数参数的意义:当将指针作为参数时,实参向形参传递的是地址,在函数执行过程中,既可以对该参数指针进行处理,也可以对该参数指针所指向的数据进行处理,(以上程序段来说就是可以对p或*p进行处理)。由于此时形参和实参都是指向同一个存储单元,因此当形参指针所指向的数据改变时,实参指针所指向的数据也作相应的改变,因此这时的形参可以作为输出参数使用。

按照上面的说法,这个程序应该没有问题的啊,实参str和形参p指向同一个存储单元,给形参分配的内存单元应该也给实参分配了才对啊,问题就是在这里。

实参和形参是指向同一个地址,它们只是指向相同,但它们自身的地址不是同时申请的,就是说p在申请内存时,str并不可以通过调用Getmemory同时申请内存,所以尽管str调用了GetMemory,但它仍然是个空指针,所以进行strcpy是就不能运行。

要使程序可以运行,只要小小的改动就行了(用指向指针的指针):

void GetMemory(char **p,int num)
{
    *p=(char*)malloc(sizeof(char)*num);      
}
void main()
{
    char *str=NULL;
    GetMemory(&str,100);                            
    strcpy(str,"hello");
    free(str);  
}

使用指针的指针,实参和形参操作的是同一块内存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值