玩转常量字符串

来源:互联网 发布:java分布式开发书籍 编辑:程序博客网 时间:2024/04/28 02:21

1.Reference: http://hi.baidu.com/benzhan/item/8c52be37ca4c9bd76c15e9f9
warning: 原文没有参考文献
2.
先撸段代码来看看

char str1[] = "abc";char str2[] = "abc";const char str3[] = "abc";const char str4[] = "abc";const char *str5 = "abc";const char *str6 = "abc";char *str7 = "abc";char *str8 = "abc";cout << ( str1 == str2 ) << endl;cout << ( str3 == str4 ) << endl;cout << ( str5 == str6 ) << endl;cout << ( str7 == str8 ) << endl;

*注:以上bool型的cout我在gcc下编译没通过,不清楚原作者是用什么编译器:(
因此,引用作者的程序结果,是:0 0 1 1
str1,str2,str3,str4是数组变量,它们有各自的内存空间;
而str5,str6,str7,str8是指针,它们指向相同的常量区域。

再来一段代码会更清楚点。

#include <stdio.h>char *returnStr_P(){    char *temp = "pointer";    return temp;}char *returnStr_A(){    char temp[] = "array";    return temp;}char *returnStr_A_S(){    static char temp[] = "static array";    return temp;}int main(){    char *str_p = NULL;    char *str_a = NULL;    char *str_a_s = NULL;    str_p = returnStr_P();    str_a = returnStr_A();    str_a_s = returnStr_A_S();    printf("str_P = %s\n", str_p);    printf("str_a = %s\n", str_a);    printf("str_a_s = %s\n", str_a_s);    return 0;}

运行结果是

str_P = pointerstr_a = ����Зc���8�}�str_a_s = static array

看出点问题了吗?以下我将原作者的思想用我的话以及我的程序结果来表述一下。

(1)因为”pointer”是一个字符串常量,存放在静态数据区,把该字符串常量存放的静态数据区的首地址赋值给了指针temp,所以returnStr_P函数退出时,该字符串常量所在内存不会被回收,故能够通过指针顺利无误的访问。

(2)“array“依然也是一个字符串常量,依然存放在静态数据区,但是把一个字符串常量赋值给了一个局部变量(char型数组temp),该局部变量存放在栈中,这样就有两块内容一样的内存,也就是说“char temp[]=”array”;”这条语句让“array”这个字符串在内存中有两份拷贝,一份在动态分配的栈中,另一份在静态存储区。这是与returnStr_P()最本质的区别。当returnStr_A函数退出时,栈要清空,局部变量的内存也被清空了,所以这时的函数返回的是一个已被释放的内存地址,所以打印出来的是乱码。其实强大的gcc已经给了warning了:

test.c: In function ‘returnStr_A’:test.c:12:2: warning: function returns address of local variable [-Wreturn-local-addr]  return temp;  ^

(3)针对前两点总结下,就是虽然returnStr_P()与returnStr_A()返回的都是一个内存地址,但是returnStr_A()中temp是先将”array” copy一份在自己的内存地址上,当函数结束时,栈空间释放,该地址上自然没用内容给str_a了。而由此我做个推断(如果有误还望细心的读者指出),起码静态存储区上的生命周期是整个程序。( PS. 经过小心求证后结果确实是如此:) )

(4)如果非得要返回局部变量的地址,那么该局部变量一定要申明为static类型,强行将temp申明为静态变量,存储于静态存储区。相信从上面的代码可以清楚的体验出来。

3.重点来了
原作者的中心思想看似有理有据,但是在没有参考文献的前提下我还是抱着半信半疑的态度翻阅了其他的一些资料,终于在 欧立奇等. 程序员面试宝典. 电子工业出版社 中找到了一些解释。

内存的分配方式有5种:静态存储区、栈区、堆区、文字常量区、程序代码区。静态存储区,内存在编译时已经分配好空间,并且生命周期为整个程序,例如全局变量、static变量。文字常量区,常量字符串就是存放在此处,生命周期也是整个程序,待程序结束后由系统释放,例如int i = 123; char *p = “hello”; 等,等号右边的这些常量均试存放再文字常量区的。这与该作者的“存放在静态存储区“有些出入。而我本人还是愿意选择更加相信后者。但我觉得通过此次,解释了平日的一些困惑,总之该作者的主思想是正确的,就是对于字符串常量的存放位置可能理解方面有些不同。仁者见仁智者见智。

以上。

0 0
原创粉丝点击