首先我们介绍一下c中内存的分配:
在一个程序编译完成后你可以有size 命令来查看,我们可一看到他存储分为三个区域,代码区域(text) 数据区(data) 和未初始化的全局变量(bss)。 这三个去有着不同的属性和意义, text去一般是read only的一位他存的是cup指令集一般不可更改,data 区存储的是已初始化的全局变量和 静态全局变量和局部静态变量以及字符常量, bss存储的是未初始化的全局变量。
在程序运行时他的内存有可以划分为5块,注意在系统自身的内存分配是从高地址向低地址进行移动的。他的五个区域分别是: 从高地址开始 1. 栈区(stack) 主要存放的是局部变量值和函数参数值。 2. 堆区(heap) 主要存放的是有malloc 分配的变量。 3. bss区 这个区的值在函数运行时可以改变。 4. data区 这个存放的变量只能初始化一次。5.text区 这里存储的是cpu指令他们或是分配便或是执行指令。 示意图如下
注意stack中的变量实在程序运行是一次吧局部变量或函数参数压入stack的,这些值可以被修改,但在函数结束时 会被释放掉,而heap则是有程序员来分配和free的他的生存周期和函数没有直接关系。
2. 我们需要了解到,在c中规定如果表达式的值是一个变量那么这变量的值就是表达式的值,如果这个表达式是一个数组那么这表达是的值就是这个数组的首地址 (这些可以在c99 规范中查到)
3 . 我们还要了解在函数运行结束后 会把他的返回值记录在一个状态寄存器中。
最后我们来探讨函数的返回值问题:
首先我们要想函数能正确的返回,那么他的返回值不可能是 stack中的变量,那么他只能是bss 和data 以及 heap中的变量。下面我们举几个例子来说明一下啊:
1.
int *test()
{
int *ret = NULL; // stack 区的变量
int num = 9; //stack区的变量
ret = #
return ret;
}
1无法正确返回
2.
int test()
{
int num = 9;
return num ;
}
2能正确的返回因为虽然num是一个stack变量 但是他返回的是变量的值,即使num被销毁 他的值依然是存下来了。
3.
int *test()
{
int ret[3]={1,2,3};
return ret;
}
无法正确返回,应为他返回的是stack中的数组地址,该地址在函数结束是销毁。
4.
char * test()
{
char test_str[5]="abcd";
return test_str;
}
无法正确返回,返回的是stack中的变量。
5.
char * test()
{
char ×test_str="abcd";
return test_str;
}
可以正确返回, 虽然他是stack的变量打他指向的地址是data段的,(c99指出表达式的值为指针是她就是这个指针的地址值)
6.
char * test()
{
static char test_str[5]="abcd";
return test_str;
}
可以真确返回,data段数据
7.
char test[45];
char * test()
{
char test_str[5]=test;
return test_str;
}
可以真确返回,bss段数据
有关还c中函数的返回值问题不要死记硬背,只要理解记忆就可以了,只要他了解到c中个变量在表达式中的白现形式,然后在根据函数return不能是stack段数据就可以很好的理解了。