在执行以下程序期间,堆栈中一段时间内绑定的最大变量数是多少:
int x, y, z;
int g(int a, int b) {
int c = 5 * a + b;
return c;
}
int f(int a, int b) {
a = g(a, 5);
return g(b, a);
}
int main() {
int a, b, c;
x = y = z = 0;
a = 5; b = 6;
c = f(a, b);
printf("%d", c);
}
如果有人知道如何找到它,请。你能解释一下我要做什么,以便在每个可能给出的代码中找到它。 没有任何优化。
另一个例子:
int x,y;
int f(int a){
if (a!=5)
return f(--a);
else
return a;
}
int main(){
int a,b;
a=8;b=6;
x=f(a);
y=f(b);
printf("%d", x+y);
return 0;
}
这是否高于答案6?因为第一次返回,返回一个变量3次..而第二次返回一次返回一个数字,我们在main中有两个变量那么6?
答案 0 :(得分:2)
您可以在脑中(或在调试器中)逐步运行程序,并可以计算call stack每个帧中的所有活动变量(然后获得它们的最大总和)。
在您的特定示例中,假设没有优化,最深的调用堆栈发生在由return c;
调用的g
调用的f
main
语句中。所以我们有3个调用堆栈帧,其中3个变量用于g
(a
,b
,c
;我假设形式类似于局部变量,这并非总是如此在实践中!),f
的两个变量(a
,b
)和main
的3个变量。
您的老师可能希望您在最深的状态下绘制调用堆栈。我把它留给你。
实际上,有几个变量不占用任何堆栈空间,例如:因为它们位于寄存器中,或与另一个变量共享一个堆栈槽。这是编译器和ABI以及处理器架构和操作系统特定的。
然而,作为Ilya answered,一个好的编译器会改变你的optimization purposes程序,所以在实践中答案可能会有所不同。
如果使用GCC,您可能会尝试查看生成的汇编程序代码(使用gcc -fverbose-asm -S
),您将看到结果和使用的变量数量取决于优化标记(即-O1
,-O2
等等......或者缺少它们。您还可以使用GCC特定的-fstack-usage标志。您甚至可以尝试-fdump-tree-all
标记到gcc
,它会提供数百个转储文件,详细说明编译器中程序的各种中间表示(Gimple,SSA,...)。
另请阅读continuations(也可能是call/cc),tail call,recursion和inline expansion上的wikipages。
BTW,调用堆栈的存在并不是C99标准所要求的严格意义(但我知道没有使用任何调用堆栈的C的实现)。如果你很好奇,你应该阅读A.Appel的旧论文garbage collection can be faster than stack allocation(它解释了SML不使用任何调用堆栈的实现,因为它正在分配每个“调用帧”,即“延续帧” ,在垃圾收集堆中。)我还建议您编译示例(使用gcc -Wall -g
),然后在gdb
调试器中逐步运行 。经常使用display
的{{1}},step
,backtrace
,frame
commands。
答案 1 :(得分:1)
这取决于编译器和优化设置。好的优化算法会生成这样的东西:
int main() {
printf("%d", 155);
}
其他算法会生成其他内容。因此,尝试使用反汇编程序来编译结果。