该代码如何在没有任何循环语句或“ goto”或递归的情况下循环?

时间:2019-01-23 05:49:32

标签: c++ c loops undefined-behavior

以下代码不包含任何循环或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

3 个答案:

答案 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

也许对于具有特定编译器的特定硬件,您总是会得到相同的行为,但这不是必须的。