我写了这段代码:
#include<stdio.h>
int valFunc(int val){
return val;
}
int main(){
int a = 5;
int b = 7;
printf("%d",valFunc(a)+valFunc(b));
return 0;
}
在 main()的 printf()函数内,调用 valFunc(a)后返回值为5,其中在调用 valFunc(b)?
之前,main函数是否保存此值5我知道如果这个函数写得如下,那么它会保存函数 valFunc(5)和 valFunc(7)的返回值。变量分别为 a 和 b 。 :
#include<stdio.h>
int valFunc(int val){
return val;
}
int main(){
int a = valFunc(5);
int b = valFunc(7);
printf("%d",a+b);
return 0;
}
但是在以前的代码中,我无法理解函数在哪里保存返回的值?它是否创建隐式变量并在调用其他函数之前使用它们来保存其进度,还是有其他机制?请解释一下。
在调用其他函数之前,是否会创建任何临时变量来将这些值存储在运行时堆栈上?在我在问题中编写的第二个代码中,很明显 main()会将这些值存储在 a 和 b 中并将它们放入在运行时堆栈上。但是 main()如何为第一个代码执行此操作,因为没有变量?
答案 0 :(得分:3)
它非常依赖于系统体系结构,但在最常见的情况下,当在C中调用函数时,结果将在特定寄存器中返回,始终相同。 如果我们专注于Intel X32-64,则返回值在寄存器 eax 中传递32位, rax 传递64.在这种情况下,编译器为IA32发出的代码将(或多或少):
lea eax, a //Get parameter address
mov eax, dword ptr [eax] //Get the value
push eax //pass parameter on stack
call valFunc //call function
mov ebx, eax //save result in register ebx
lea eax, ba //Get parameter address
mov eax, dword ptr [eax] //Get the value
push eax //pass parameter on stack
call valFunc //call function
add eax, ebx //sum the results
push eax //pass the sum as parameter on stack
lea eax, fmtstr //Get the address of the format string "%d"
push eax //push it onto the stack
call _printf
作为变体,结果可以保存在堆栈中(即在所有寄存器都在使用的情况下):
....
call valFunc //call function
push eax //save result on the stack
lea eax, ba //Get parameter address
mov eax, dword ptr [eax] //Get the value
push ebx //save ebx on the stack
mov ebx, eax //save result in register ebx
call valFunc //call function
add eax, ebx //sum the results
pop ebx //Restore register ebx from stack
push eax //pass the sum as parameter on stack
....
我希望这澄清了这一点。
答案 1 :(得分:2)
有趣的是,您并不担心a+b
。但这是一个非常相似的事情。
更复杂的表达式的中间值存储在某个地方。在寄存器中,在内存位置,在堆栈上......由编译器决定。是的,您可以将它们视为临时变量......但实际上,它们并不是您的关注点。
在我在问题中写的第二个代码中,很清楚 main()将这些值存储在a和b中,并将它们放在运行时 堆
由编译器决定。它可以检查你是在进行简单的操作,直接在编译时计算最终结果,即12,然后发出一个直接用12调用printf的代码。
这是as-if规则。只要您的应用程序具有相同的可观察方式(在本例中为print 12),编译器就可以执行任何操作。