原文:http://tanghao0730.blog.163.com/blog/static/164247135201051153152371/
C中内存分配有三种方式
【1】静态存储区分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量、static静态变量。
【2】在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动释放。
【3】从堆上分配。也称动态内存分配,在程序运行时用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放。生存期由程序员决定。
在进行C/C++编程时,经常需要操作的内存可分为以下5个类别。
1:栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等。
2:堆区(heap):由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。
3:全局区(静态区)(static):存放全局变量、静态变量和常量。全局变量和静态变量的存储在一起的。程序结束后由系统释放。
4:文字常量区:常量字符串就是放在这里,程序结束后由系统释放。(文字常量区就是数据全局区?)
5:程序代码区:存放函数体的二进制代码。
参考参考《程序员面试宝典》p68一个题目。
char *strA()
{
char str[ ]="hello world";
return str;
}
首先要搞清楚char str[ ]="hello world"和char *str="hello world"这两者的区别。书上说char str[ ]="hello world"分配的是一个局部数组;char *str="hello world"分配的是一个全局数组,可以再深入阐释一下:
char *str="hello world" ,函数的局部变量只占了4个字节,因为它只声明了一个指针,该指针存于栈区,而"hello world"字符串内容是存放于文字常量区的,指针str就指向了这个常量区。比如"hello world"被编译器分配到0x2000到0x2011这段长度为12的内存区里,那么char *str="hello world" 语句运行时就相当于 char *str=0x2000。
char str[ ]="hello world",函数的局部变量分配了12个字节,该语句相当于char str[10]={104,101,108,108,111,32,87,119,111,114,108,100};字符串的内容时直接放在函数用的内存里边。
回到之前的题目,可知str里存在的地址是函数strA栈帧里"hello world"的首地址,但是在函数调用完成,栈区自动释放,栈帧回到调用strA之前的状态,return str无法得知当前栈区状态,所以程序无法输出正确结果。
可修改如下:
const char *strA()//定义为const型,限定变量不允许被改变。
{
char *str="hello world";
return str;
}
或者
const char *strA()
{
static char str[ ]="hello world"; //str被定义为static,函数结束之后不释放,保留当前栈区状态。
return str;
}
//===============================================
我自己加了一个例子,经典例子
#include <stdio.h>
int main (void)
{
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";//虽然没写const,但其实和5,6是一样的
char *str8 = "abc";
printf("%d/n",( str1 == str2 ));
printf("%d/n",( str3 == str4 ));
printf("%d/n",( str5 == str6 ));
printf("%d/n",( str7 == str8 ));
printf("%d/n",( str5 == str8 ));
printf("%s/n",str5);
str7[1]='X'; //想换成aXc,没门!abc存在字符常量区,是常量,不可更改
printf("%s/n",str5);
return 0;
}