标签:
题目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