#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成为甚至存在于功能之外。它存储价值在哪里?堆栈还是堆?
答案 0 :(得分:9)
既不在堆栈上也不在堆上。
至少在x86架构中,函数的返回值通常被复制到eax
寄存器,因此它会在函数之外存在。这就是为什么你不能返回数组而只是指向它的指针的原因之一。
但是,您可以按值返回结构和其他更大的变量,在这种情况下,编译器通过使用堆栈和其他寄存器(如edx
)来执行一些操作。
答案 1 :(得分:5)
return
实际上做什么取决于编译代码的机器架构。在具有寄存器的机器上,将x
的值复制到寄存器。调用者将从那里获取值并对其执行某些操作。此处,该值将复制到名为a
的变量中。
如果在堆栈计算机上编译此代码,则返回值可能只留在堆栈本身上。调用add
函数的目标代码如下所示:
push 7
push 5
call add
seti 0x28ccf4
add
将弹出堆栈中的值,将它们一起添加并将结果推回堆栈。 (如果函数处理的数据结构无法在堆栈的插槽中找到,则会推送它们的地址。)seti
是一个操作,它将从堆栈中弹出一个值并将其分配给整数变量at一个特定的地址。 (此处,0x28ccf4
是a
的地址。)。由于堆栈顶部现在包含添加5
和7
的结果,因此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'。函数内声明的自动变量存在于调用堆栈上该函数的激活记录中,并且在将任何返回值复制回调用者的变量之后,在函数执行结束时删除激活记录。