简单的C程序输出42
令我惊讶。我希望它输出一个垃圾值或0
,因为foo()
和bar()
的堆栈帧不同。输出如何确定为42
?
#include <stdio.h>
void foo(void){
int a;
printf("%d\n",a);
}
void bar(){
int a=42;
}
int main(){
bar();
foo();
return 0;
}
>>gcc -o test test.c
>>./test
42
当我指示编译器优化代码时,它会打印垃圾!
>>gcc -O -o test test.c
>>./test
2487239847
答案 0 :(得分:2)
是的,值42是垃圾。以下是对它的解释:
堆栈中的每个函数都与此顺序类似
在上面的示例中,调用main()
并遵循上述过程。
然后遇到bar()
后面提到的1,2,3,4步骤然后将局部变量a=42
存储在内存中(5)然后6,7跟随它然后它会出来记忆。
然后它遇到foo()
跟随1,2,3,4步骤在bar()
的内存位置相同。并且您声明了一个名为a
的局部变量,它将指向bar()
持有局部变量a=42
的相同内存位置。所以它在打印时给出相同的值42,这实际上是一个垃圾值。
要验证这一点,请尝试以下示例:打印7
#include <stdio.h>
#include <string.h>
void foo() {
int b;
printf("%d\n",b);
}
void zoo() {
int dummy = 7;
}
void bar(){
int a1=3;
}
int main(){
bar();
zoo();
foo();
return 0;
}
参考:Doc
答案 1 :(得分:1)
函数调用继续堆栈(它们的激活记录),在这种情况下,两个函数foo和bar在参数,返回类型和每个函数内的局部变量方面是相同的。因此,第一次调用会在堆栈上放置一些内容,一旦完成,它的激活记录就会被弹出但不会被清除(编译器不会生成代码来清理它们)。现在,第二个函数调用本质上最终使用相同的内存位置,因此使用相同的内存区域从前一个调用获取值。未在函数中初始化的值被视为未定义。在foo和bar的情况下,由于两个函数的类似签名以及变量的相同类型和位置,我们得到了相同的值。尝试在一个函数中添加两个整数或整数和一个浮点数,然后在下一个中反转顺序,您将看到效果。当然,当你调用优化器时,它可能会把东西放在寄存器上,因此当编译器看不到优化的余地时,你可能得到未定义的值,就像foo一样。