二重指针的2个例子

1.

二重指针的2个例子

b那块内存,已经不被任何变量占用,属于不被管理的内存。b被回收,那块内存的内容并不会立刻被改写。
q is dirty after function'fun'!在执行完fun函数之后,q就变成了一个危险的指针。(p是二重指针,相当于&q,那么*p就相当于q了,是一个地址!)
 
2.(一道面试题,原博客地址http://blog.csdn.net/sdfgh2046/article/details/5647913)
总结:函数“地址传递”调用函数时必须用 函数名(&a)的方式。不加&就是值传递。指针也是变量,虽说他存储的是别人的地址。如果想把指针作地址传递,就必须使用地址的地址,即二重指针。

<pre name="code" class="cpp">#include<stdio.h>
#include<memory.h>
#include<string.h>
void Getmemery(char *p)
{ 
   p=(char *)malloc(100); //其实此函数改变的是形参p,而非main函数中的str
}                         //要想在函数中改变str,就需要改变指向str(指针)的指针值,即二重指针的值!
void main()
   char *str=NULL; 
   Getmemery(str); 
   strcpy(str,"helloworld"); 
   printf("%s",str); free(str);
}


 

 编译没有问题的,但是为什么执行的时候会错误退出呢?根据现象,很明显是指针的非法访问了,但是问题在哪里,我一时也蒙了,或者说被他的思路给引导到了一个错误的方向。当然,最简单的解决办法是返回一个指针就没有问题,稍微修改一下 
 

#include<stdio.h>
#include<memory.h>
#include<string.h>

char *Getmemery(void)
{
   char *p=(char *)malloc(100);
   return p;
}
void main()
{
    char *str=NULL;
    str = Getmemery();
    strcpy(str,"helloworld");
    printf("%s",str);
    free(str);
}

这样代码执行的很正常,这种风格也是很常用的,也就作罢。

但是为什么第一个程序不正确?理论上,按照理论上分析是“正确”的,心里一直有个结,解不开这个题目,心里总是有点不舒服。
直到今天在ouravr上面看到有个关于 typedef用法的帖子,突然引起了我的兴趣,自己关于指针的,特别是二维数组和数组指针并不是理解的很透侧,于是就趁此机会好好的复习一下二维数组。
最后终于将之前的一个问题想明白了。
正确的代码如下:

#include<stdio.h>
#include<memory.h>
#include<string.h>

void Getmemery(char **p)
{
    *p=(char *)malloc(100);         //注意char *与*p是对应关系
}

void main()
{
    char *str=NULL;
    Getmemery(&str);
    strcpy(str,"helloworld");
    printf("%s",str);
    free(str);
}

我们应该使用的是二重指针来完成任务。

分析一下之前的程序为什么会错了。

(1)void Getmemery(char *p)

(2)char *str=NULL;

(3)Getmemery(str);

1中子程序的形参是一个指针,然后很自然会想到2,3中的调用方式,本来的想法是用malloc分配内存,然后修改传入的指针变量,那么最后就根据通过

strcpy(str,"hello world");就可以向分配的内存里面写数据了。一切都是那样流畅,对,因为这个用法平时用习惯了,所以根本不会去考虑正确性。

然而,这里就出问题了。首先,Getmemery(str) 传递的是str指针的地址,这个没有问题,C不同于C++,参数是通过传递的,而不是通过引用。也就是说,实际参数 str先自己copy一份,然后传递给形式参数 *P接收,这个C语言的指针的时候已经强调多次了,但是自己还是错了啊,哈哈。

然后,在子程序里面,如果通过 *P 那么访问到的将是 *str的内容,这是等价的。但是,本程序一个致命的错误,非常隐蔽,那是子程序企图修改p(地址)的内容,而不是 *p(字符串数组)的内容!! 这个错误找了我很久终于给揪出来了。修改了 p的值是没有意义的,这个值是形式参数,并不会返回任何的东西,而 *p则是通过p的地址直接访问需要的变量,这是不同的用法。所以说白了,void Getmemery(char *p)执行之后并没有改变任何的东西,str的值并没有修改过,保持NULL,所以访问 *0 地址会被操作系统禁止,得到一个错误。

解决办法,是用2重指针。目的是要修改指针的地址,但是按照上面的分析,我们并不能去修改,但是我们可以用2重指针,将*str的地址值str,用2重指针来改变。

void Getmemery(void **p)
{
     *p=(void **)malloc(100);
}

子程序修改为这个样子,出入的参数也得修改

char *str=NULL;
Getmemery(&str);

那么可以这样理解,因为形参是2重指针,所以 p (二重指针)对应 &str ,*p (指针,字符串数组首地址)对应str,之前说了,我们的目的是要修改 str的值,所以很自然,我们用 *p = xxx这样的形式去修改了。

 

为什么二重指针能够完成任务呢?(在调用函数的情况下)

想一想我们平时是怎样调用函数用指针的方式来改变实参的,不就是直接改变指针所指向的值么?(老谭的书例8.3,其实质不是传值,而是改变指针指向的值,*p(假设p是一个指针)),在这里要想改变str的值怎么办?str本身就是一个指针,“改变指针所指向的值”就变成了“改变指针的所指向的指针”,显然要传递的就是二重指针了!

简而言之,此例向我们展示了如何改变指针的值,即传递二重指针!(类比于改变一个变量的值要用一级指针的传递方式来理解)而在函数体中,指针的值就是*(二重指针变量)——剥掉一层。

如果我们没有用调用函数的方式,而是在主函数中直接就开辟空间给char*,就无须定义二重指针,如

#include<stdio.h>
#include<string.h>
#include<memory.h>
void main()
{
    char*str=NULL;
    str=(char*)malloc(100);             //申请指针str所指向的块的大小,此空间在堆中,必须手动释放。
    strcpy(str,"hello world");
    printf("%s",str);
    free(str);
}

这和建立动态链表的方法是一致的,如

struct student*p1,*p2;

p1=p2=(struct student*)malloc(sizeof(struct student ));

这实际上是和那个调用函数返回指针的方法是一致的,它们的实质就是申请指针str所指向的块的大小,即改变str的值!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值