以下代码不包含任何循环或goto
或递归;但是它在控制台中从1打印到10。
#include <stdio.h>
int n = 1;
void foo() {
int x;
printf("%d ", n);
if (++n>10) return;
*(&x+4) -= 5;
}
int main() {
foo();
return 0;
}
这个神秘的代码*(&x+4) -= 5;
导致了循环。
据我所知-x
的值保存在堆栈存储器中。可能是,在(&x+4)
之前有函数foo
的指针,并且foo
被递归调用。
然后,我不确定我的假设是否正确。我也不清楚5
的来源。我试图打印和分析函数指针和变量的地址(由我的同事建议)。并用我对C memory layout的了解来匹配它们。但是我变得更加困惑。
如果在x
之前和之后声明了更多变量,*(&x+4) -= 5;
将会如何变化?
操作系统: Windows-7 64位,编译器: GNU GCC,编辑器: CodeBlocks 16.01
答案 0 :(得分:3)
*(&x+4) -= 5;
的行为是不确定的,因为它写在程序分配的任何对象的边界之外。这将取决于在该地址存储的内容(如果有)。因此,对于您的代码为何如此奇怪的一个简短答案是,该代码具有一个导致其行为不可预测的错误。
您的平台上可能正在发生的事情是,它可能最终修改了它返回的地址,从而导致它在调用main
之前返回到foo
,从而导致{{1} }再次致电main
。
答案 1 :(得分:2)
大卫是对的。当代码试图写入甚至访问未分配给它的内存块中的任何内容时,它可以做任何事情(即使存在某个函数的地址与反应堆一起运行,即使发生核爆炸)。由于C不是强类型语言,因此您有责任注意内存分配。巧合的是,它引起了循环。在我的系统上,它按预期工作。
答案 2 :(得分:1)
您正在修改*(&x+4) -= 5;
中的堆栈,这是未定义的行为,在未定义的行为下,任何事情都可能发生,甚至使恶魔从您的鼻子中飞出来。参见http://catb.org/jargon/html/N/nasal-demons.html
也许对于具有特定编译器的特定硬件,您总是会得到相同的行为,但这不是必须的。