c语言函数为什么可以return局部变量,局部变量不是被释放了吗

之前的几篇文章中的实例代码中,我们用到了不少 return 语句,现在是时候深入学习一下,总结一波了。

在有返回值的函数中,return 语句的作用是提供整个函数的返回值,并结束当前函数的执行。在没有返回值的函数中也可以使用 return 语句,例如当检查到一个错误时提前结束当前函数的执行。请看下面这个例子:

int add(int a, int b)
{
    return a+b;
}
void print_log(double x)
{
    if(x <= 0.0){
        printf("error\n");
        return;
}
    printf("log(x)=%f\n", log(x));
}
int main()
{
    int sum;
    sum = add(2,3);
    print_log(3.2);
    return 0;
}

对于 print_log 函数,它是 void 型,没有返回值,return 在这里起到提前结束的作用。因为我们要打印出 x 的对数值,所以 x 必须是个正数。print_log 函数则对 x 的值做了判断,如果它不大于 0,则打印出 error,就直接返回 print_log 函数,并且返回到调用它的地方接着执行下一步了。

而像 add 这样的有返回值的函数,return 则相当于定义一个和函数返回至类型相同的临时变量,并且用 return 之后的表达式进行初始化。但是,这个临时变量比较特殊,我们只是读一下它的值,读完了就释放了,而不能往里面存新的值,简单来说,就是函数返回值不能做左值,下面这么写就是非法的:

add(2,3)=4;         // 非法

现在已经对 return 的用法了解了,但是还有一点点疑问

还记得上面这张图吗?在上一节中,我们提到程序每调用一个函数,就会在栈区为其分配一块区域,所有局部变量都是在这块区域里存放的,函数执行完毕返回后,系统自动就将这块区域收回了。

这块区域较为正式的名字叫“栈帧”。


那么问题来了,既然函数的局部变量都存放在栈区,栈区在函数返回就释放了,那为什么 add 函数还能把局部变量返回呢?其实函数返回的并不是局部变量,而是局部变量里面存放的数据。

在之前,我们用鞋柜来比喻局部变量,用鞋子来比喻数据。我们想取出的是鞋子,而不是鞋柜,对吗?

事实上,在函数执行完毕后,系统会先将返回值暂存在寄存器 eax 里,所以即使函数的栈帧被系统收回了,它的返回值依然在 eax 里保存的很好。函数返回后,系统再把返回值从 eax 中取出,赋值给调用者。请看下面这个例子:

#include <stdio.h>
int fun()
{
    return 1;
}
int main()
{
    int ret;
    ret = fun();
    return 0;
}

我们查看它的汇编代码,发现一切和我们预料的一致:

阅读更多:   C语言
已有 2 条评论
  1. Far From Home

    写的很清楚, 没有学过汇编的我, 流下了感动的泪水

  2. sheehan

    问下如果不是加法运算的话,也是存在eax里么,还是别的什么寄存器

添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif