c语言中函数返回局部变量的指针(一些容易犯错的地方)

来源:互联网 发布:淘宝一伍一拾 编辑:程序博客网 时间:2024/05/18 02:02

写这篇博客是我一直以来遇到的一个指针的问题-----对于返回一个局部对象的指针到底能否达到预期的效果?我也还在摸索之中,能给大家有所启发吧。

 

首先我先给出一些最近我做题过程中遇到的一些问题。

比如很经典的strcpy函数的编写,估计很多人早已看过了。转载的文中,给出了2分到10分的样式。着实让人感叹

2 分
void strcpy( char *strDest, char *strSrc )
{
while( (*strDest++ = * strSrc++) != ‘\0’ );
}
4 分
void strcpy( char *strDest, const char *strSrc )
//将源字符串加const,表明其为输入参数,加2 分
{
while( (*strDest++ = * strSrc++) != ‘\0’ );
}
7 分
void strcpy(char *strDest, const char *strSrc)
{
//对源地址和目的地址加非0 断言,加3 分
assert( (strDest != NULL) && (strSrc != NULL) );
while( (*strDest++ = * strSrc++) != ‘\0’ );
}
10 分
//为了实现链式操作,将目的地址返回,加3 分!
char * strcpy( char *strDest, const char *strSrc )
{
assert( (strDest != NULL) && (strSrc != NULL) );
char *address = strDest;
while( (*strDest++ = * strSrc++) != ‘\0’ );
return address;
}

[可是,到最后我就有问题了,对于10分的这个strcpy函数的描述,有一点我断言它肯定有错误----就是它返回的是一个局部对象的指针,而在以前我一直“坚信”返回一个局部对象的指针是错误的,之所以认为它会出错是因为在函数返回的过程中,它会释放内存,内存中的数据变得不可预料了。而且在看c++ primer的书中也是这么说的,但它没有给出什么实际的例子。(如果是我的软件有问题或者大家有通过编译的,欢迎指出交流)

为了能得到验证,我用vc++6.0在自己的电脑上尝试了一下,果然确实出现了错误,尽管编译什么的都通过了。很惭愧的是,自己不会真正的使用vc++,连怎么去看它的内存,地址,参数的都不会,只会也只知道看结果。。深感惭愧,没有听前辈的话--《c语言深度解剖》。]----------------------

PS:(20130504)最近有遇到类似的的题目,又自己检验了一遍,strcpy()函数没有出错。对于是否能返回局部对象的指针问题有待进一步解决。。。。

 

随后我又想起了以前自己做过的一道题就是有关个getmemory()函数的基本用法,里面也涉及到了很多有关指针的问题。设想,难道返回指针都是错误的?但是,翻翻书,在谭浩强的课本中,299页建立链表的时候明明返回的也是指针。这究竟又是为什么?最后自己在网上苦心的查找资料。

有人是这么解释的:“函数不能通过返回指向栈内存的指针,但对于堆内存的指针却是可以的”。以前一直对栈和堆的认识也不是很深,又顺便网上查了些资料有关数据存储的,就是下面我提到的参考博客之一,很有用。

以下给出一道题,大家分析分析:

1.

#include <stdio.h>  

char *returnStr()  

{  

    char *p="hello world!";  

    return p;  

}  

int main()  

{  

    char *str;  

    str=returnStr();  

    printf("%s\n", str);  

    return 0;  

2.

#include <stdio.h>  

char *returnStr()  

{  

    char p[]="hello world!";  

    return p;  

}  

int main()  

{  

    char *str;  

    str=returnStr();  

    printf("%s\n", str);  

   return 0;  

}  

大家也可以亲自去编译一下。不知道大家会认为以上的哪个可以正常运行,而哪个又不可以。仅仅是一个字符串指针和字符数组的区别。第一个,“hello world!”是字符串常量,存放在常量存储区,而这些内存中的数据是不会随着函数的调用完成而释放的,只有程序结束了才会消亡,因此当把它的地址返回时,还能找到这些内存存放的数据;有人可能会问,难道第二个中的“hello world!”难道不是存储在常量存储区吗?不都是一样的吗?它是存储在常量存储去,但是它是作为赋值给p的数组元素,而我们此时返回的是数组p的首元素地址,而数组p存储的是“hello world!”的副本,也就是将常量存储区的数据存储到了数组里,而在数组里面的数据时存放在栈里面的;这样的话,在函数返回的时候,要进行出栈也就是内存的释放(这些内存里面到底存储的是什么数据也就不得而知了),返回的是一个内存已经释放了的指针,所以会出现错误。

 

对于指针方面的问题,将继续收集;以上的内容有纰漏之处希望大家指出。

 

参考的一些博客资料:

http://blog.csdn.net/qustdjx/article/details/7919709

http://blog.chinaunix.net/uid-11959329-id-3268560.html

http://www.cnblogs.com/Kevin_z/archive/2010/03/05/1679031.html

原创粉丝点击