以下代码生成y是答案,但我从未将42分配给y,怎么可能是42?
#include <stdio.h>
void doit2(void)
{
int x;
int y;
if (x == 42)
{
printf("x is the answer\n");
}
else if (y == 42)
{
printf("y is the answer\n");
}
else
{
printf("there is no answer\n");
}
}
void doit1(int a)
{
int b = a;
}
int main(void)
{
doit1(42);
doit2();
}
Run Code Online (Sandbox Code Playgroud)
rlb*_*ond 12
这是由于调用函数的方式.当doit1被调用时,参数a(42)被放置在调用堆栈上,和b(也42)正上方.当你退出doit1并进入doit2,x并且y在同一个地方a并且b在doit1.由于两者都没有被初始化,所以它们只使用该点中已有的任何值 - 在您的情况下为42.当然,取决于优化,这可能不会总是发生,但它是一个相当不错的选择.
维基百科有一篇关于调用栈如何工作的文章.
Mar*_*off 10
会有一些答案指出堆栈/寄存器/临时变量的问题,但我会指出,如果你使用优化进行编译,则没有答案.
$ gcc -O3 42.c -o 42 $ ./42 there is no answer $ gcc -O2 42.c -o 42 $ ./42 there is no answer
此外,当您不进行优化时,答案似乎取决于您的编译器:
$ gcc 42.c -o 42 $ ./42 x is the answer $ tcc -run 42.c y is the answer
在GCC中,未经优化的 doit2导致此程序集:
doit2:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
cmpl $42, -4(%ebp)
jne .L2
movl $.LC0, (%esp)
call puts
jmp .L5
.L2:
cmpl $42, -8(%ebp)
jne .L4
movl $.LC1, (%esp)
call puts
jmp .L5
.L4:
movl $.LC2, (%esp)
call puts
.L5:
leave
ret
Run Code Online (Sandbox Code Playgroud)
优化后,我们甚至不会与42进行比较:
doit2:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $.LC2, (%esp)
call puts
leave
ret
Run Code Online (Sandbox Code Playgroud)