二重指针的一个问题分析
2009-10-25 14:49
323 查看
#include <stdio.h> #include <stdlib.h> #include <string.h> void Getmemery(char *p) { p=(char *)malloc(100); } void main() { char *str=NULL; Getmemery(str); strcpy(str,"hello world"); printf("%s",str); free(str); }
编译没有问题的,但是为什么执行的时候会错误退出呢?根据现象,很明显是指针的非法访问了,但是问题在哪里,我一时也蒙了,或者说被他的思路给引导到了一个错误的方向。
当然,最简单的解决办法是返回一个指针就没有问题,稍微修改一下:
#include <stdio.h> #include <stdlib.h> #include <string.h> char *Getmemery(void) { char *p=(char *)malloc(100); return p; } void main() { char *str=NULL; str = Getmemery(); strcpy(str,"hello world"); printf("%s",str); free(str); } |
但是为什么第一个程序不正确?理论上,按照理论上分析是“正确”的,心里一直有个结,解不开这个题目,心里总是有点不舒服。
直到今天在ouravr上面看到有个关于 typedef 用法的帖子,突然引起了我的兴趣,自己关于指针的,特别是二维数组和数组指针并不是理解的很透侧,于是就趁此机会好好的复习一下二维数组。
最后终于将之前的一个问题想明白了。正确的代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> void Getmemery(void **p) { *p=(void **)malloc(100); } void main() { char *str=NULL; Getmemery(&str); strcpy(str,"hello world"); 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) 传递的是 srt指针的地址,这个没有问题,C不同于C++,参数是通过传递的,而不是通过引用。也就是说,实际参数 srt 先自己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 这样的形式去修改了。
这样得到的程序就正确了。2重指针,使用起来还是有点晕,得多加练习。
相关文章推荐
- C语言中一个指针传递问题的分析
- 二重指针的一个问题
- (遇到的一个问题)空指针引用, 是可以改变这个指针所指内容的。
- 对于一颗完全二叉树,要求给所有节点加上一个pNext指针,指向同一层的相邻节点;如果当前节点已经是该层的最后一个节点,则将pNext指针指向NULL;给出程序实现,并分析时间复杂度和空间复杂度。
- 48_类加载器的一个高级问题的实验分析
- C++字符数组越界问题的一个案例分析
- 嵌入式软件开发------指针和内存释放的问题分析
- 目前住院病人主要由护士护理,这样做不仅需要大量的护士,而且由于不能随时观察危重病人的病情变化,还可能会延误抢救时机。某医院打算开发一个以计算机为中心的患者监护系统,试写出问题定义,并且分析开发这个系统的可行性。
- 前两天困扰我的一个关于指针和内存的问题的总结
- C++ 二级指针、函数指针与数组复合类型的问题分析
- 高速信号常见问题分析(一)——一个25MHZ时钟信号的单调性问题测试分析
- 转载:VC运行库版本不同导致链接.LIB静态库时发生重复定义问题的一个案例分析和总结
- 一个关于二维指针的问题
- 求解一个简单的创建单链表的问题为什么用二级指针 ?
- 《Java程序员面试宝典》P99例题3的一个问题分析
- 关于一个指针问题的困惑
- 一个空指针问题
- 一个实际问题分析及解决之七:理解websphere的classloader
- VC运行库版本不同导致链接.LIB静态库时发生重复定义问题的一个案例分析和总结
- Java调用Microsoft exchange ews接口空指针问题分析