return语句在哪里保存其数据?

时间:2011-07-20 05:55:33

标签: c

#include<stdio.h>

int add(int,int);

int main()
{
    int a;
    a=add(5,7);
    printf("%d",a);
}

int add(int x,int y)
{
    x=x+y;
    return(x);
}

昨晚我对回复声明表示怀疑。请参阅x是在add函数内定义的自动变量,并且ANSI表示存在自动变量并且仅在函数内部使用其生命周期,但此处return语句可以使变量a成为甚至存在于功能之外。它存储价值在哪里?堆栈还是堆?

6 个答案:

答案 0 :(得分:9)

既不在堆栈上也不在堆上。

至少在x86架构中,函数的返回值通常被复制到eax寄存器,因此它会在函数之外存在。这就是为什么你不能返回数组而只是指向它的指针的原因之一。

但是,您可以按值返回结构和其他更大的变量,在这种情况下,编译器通过使用堆栈和其他寄存器(如edx)来执行一些操作。

答案 1 :(得分:5)

return实际上做什么取决于编译代码的机器架构。在具有寄存器的机器上,将x的值复制到寄存器。调用者将从那里获取值并对其执行某些操作。此处,该值将复制到名为a的变量中。

如果在堆栈计算机上编译此代码,则返回值可能只留在堆栈本身上。调用add函数的目标代码如下所示:

push 7
push 5
call add
seti 0x28ccf4

add将弹出堆栈中的值,将它们一起添加并将结果推回堆栈。 (如果函数处理的数据结构无法在堆栈的插槽中找到,则会推送它们的地址。)seti是一个操作,它将从堆栈中弹出一个值并将其分配给整数变量at一个特定的地址。 (此处,0x28ccf4a的地址。)。由于堆栈顶部现在包含添加57的结果,因此a的值将变为12

答案 2 :(得分:4)

它有所不同。在典型情况下,您可以依赖至少在某些寄存器中返回int的大小(例如,通常在x86上为eax,在MIPS上为$ v0- $ v1,在ARM上为r0) )。

在许多机器上,较大的返回值(例如,具有多个成员的结构)将导致调用者在堆栈上分配空间以保存返回值,并将指向该空间的指针作为函数的隐藏参数传递,或者函数具有隐含的知道该空间相对于(例如)输入函数时的堆栈指针的位置。

虽然问题标记为C,但我还要提到在C ++中有一些关于返回值的特殊规则。具体来说,有一个返回值优化和一个命名的返回值优化。这些允许编译器忽略复制返回值的代码,即使/例如(例如)副本通常具有可见的副作用。这些旨在允许优化函数构造返回值,其中调用代码将需要它,而不是在函数中本地构造它,然后将副本复制回调用代码可以使用它的位置。

答案 3 :(得分:3)

它存储在我所知道的大多数平台的寄存器中,但这可以通过编译器实现来改变。

值得注意的是,虽然return x其中x是值而不是指针,例如在你的情况下是合法的,如果x是指针,你应该确保缓冲区/数据它指向函数返回时有效,否则它将是指向无效位置的有效指针。

答案 4 :(得分:2)

如果您是CS学生,这很可能包含在编程语言课程中。无论如何,你可以查看Wikipedia

事实上,它存储在call stack, aka stack

答案 5 :(得分:1)

add函数的返回值被复制回main函数中的'a'。函数内声明的自动变量存在于调用堆栈上该函数的激活记录中,并且在将任何返回值复制回调用者的变量之后,在函数执行结束时删除激活记录。