码迷,mamicode.com
首页 > 其他好文 > 详细

函数与指针参数——关于两道题目的个人理解

时间:2015-07-23 19:22:20      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:

题目1,下面的代码的输出结果是什么

 1 #include<stdio.h>
 2 
 3 void get(char *p)
 4 {
 5     p="hello!";
 6 }
 7 
 8 int main(int argc, char const *argv[])
 9 {
10     char *str=NULL;
11     str = get();
12 
13     printf("%s\n",str);
14 
15     return 0;
16 }

读者也可以自己思考一下答案是多少,当时我不假思索地写了:hello!

 

结果答案却是输出乱码,测试了一下指针str还是指向NULL,这是为什么呢?

 

原来我在这里面犯了个常见的关于实参和形参的低级错误。

先看下面这段经典的学校教函数时用指针作为参数的swap代码:

1 void swap(int *p,int *q)//交换2个整数
2 {
3     int temp;
4     temp=*p;
5     *p=*q;
6     *q=*p;
7 }

这段函数在这里是不用返回值的,很多书都拿这段代码来作为函数中指针间接修改变量的例子。

最近在系统巩固C语言,所以这段代码块看的多了,导致一看到指针变量作为函数的参数传递进去,就傻傻地默认了拥有指针参数的函数一旦有指针传递进去,那么该传递进去的指针在函数里面的操作会影响到该指针。其实这样的是的!其实仔细回想指针的知识,在这段代码中,其实是利用p、q两个指针指向的地址去修改对应的变量,即用*运算符去对象后去修改的对应的数据的。

好比如 爸爸给了小明(swap()这个函数) p和q这2把钥匙让他去把2个对应房间的家具互调,最后小明不用把房间的钥匙给回爸爸,房间的家具实际上已经互调了。

回头看一下上面的题目

1 void get(char *p)
2 {
3      p="hello!";
4 }

这里说白了p就是个参数,既然作为参数传递进去,你想到得到其结果,就应该把他return回来!否则一旦这个函数调用完毕,系统就会释放他,p也就没有了,就是个临时工。

运行这个函数就好比如,小明去钥匙店(函数get(char *p))配了一把房间(也就是常量"hello!")的钥匙p,然后钥匙都没拿就走了,老板要这个钥匙也没用,就把它扔了,也就是运行完get()之后,p就没了,被释放了,根本没把这钥匙交给任何人!函数的调用者小明也没有得到任何东西,白跑一趟。

所以程序应该修改为:

1 char *get(char *p)
2 {
3     p="hello";
4     return p;
5 }

这样才能把在get(char *p)里面配的钥匙p给return出去,才能交给函数的调用者(来配钥匙的人)。


 

题目2:求下面的函数输出:

 1 #include<stdio.h>
 2 
 3 char *get(void)
 4 {
 5     char p[]="hello!";
 6     return p;
 7 }
 8 
 9 int main(int argc, char const *argv[])
10 {
11     char *str=NULL;
12     str = get();
13 
14     printf("%s\n",str);
15 
16     return 0;
17 }

乍一看好像答案又是:hello!

其实是错的,答案还是乱码!

相信很多人学习指针和数组的时候,在脑袋里就被这样一句话给框住——“数组名就是指向其数组首元素的指针常量”

比如char a[]=“abc”;

那么printf("%c",a);

输出就是:a

答案也确实是如此,于是很多人就把上面的子函数char *get(void)的功能以为是:

【返回指向字符串常量"hello!"首地址的一个字符指针】

其实这样的理解是错误的,先来看看调用这个函数

str=get();

这一过程系统是怎么处理的。

技术分享

1、声明一个字符数组p[],并且系统把存储在静态储存区的字符串常量"hello!"复制到p指向的连续内存空间上!

2、返回指针p的地址

3、(重要)这是个子函数,所以系统自然会释放掉函数中的临时变量char p[]

请看好第3步,p的地址虽然给了str,但是p指向的那片内存在get()运行后就释放了,所以复制过来的"hello!"也就没了!

所以当主程序再去printf指针str指向的区域,出来的就不是"hello!",而是乱码,因为子函数中临时的"hello!"已经释放掉了!

所以程序可以修改如下,输出结果就是正确的:

1 char *get(void)
2 {
3     char *p="hello";
4     return p;
5 }

到这里有读者就会问了,不都是个指针p指向字符串"hello!"吗?为什么结果不一样呢?

下面来看一下上面修改的程序的运行过程:

技术分享

可以看出,当定义为指针类型时,p存放"hello!"在静态存储区中的地址,所以p给了str后,printf("%s",str)就能打印出hello!

透过现象看本质

1、当定义为char p[]="hello!";

 的时候,p就固定下来,是一个指针常量!指向的内存放着拷贝过来的"hello!"     (‘h‘,‘e‘,‘l‘,‘l‘,‘o‘,‘!‘,‘\0‘)

2、当定义为char *p="hello!"的时候,则p是直接指向静态存储区的"hello!"

 

 

 

本文为原创,转载请注明出处。


 

函数与指针参数——关于两道题目的个人理解

标签:

原文地址:http://www.cnblogs.com/suiyek/p/4670748.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!