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

How This Code Loops Without Any Loop Statement or 'goto' or Recursion?

以下代码不包含任何循环,或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;会怎样变化?


OS: Windows-7 64 位,编译器: GNU GCC,编辑: CodeBlocks 16.01

*(&x+4) -= 5; 的行为未定义,因为它写入程序分配的任何对象的边界之外。这将取决于存储在该地址的内容(如果有的话)。因此,对于您的代码为何表现如此奇怪的简短回答是,该代码存在一个导致其行为不可预测的错误。

您的平台上可能发生的情况是,它可能最终会修改它 return 指向的地址,导致它在调用 return 之前变为 main =12=],导致 main 再次调用 foo

大卫是对的。当代码试图写入或什至访问未分配给它的内存块中的某些内容时,它可以做任何事情(甚至是核爆炸,如果有,比方说,某个函数的地址与反应器有关)。负责内存分配是您的责任,因为 C 不是强类型语言。它导致循环只是巧合。在我的系统上,它按预期工作。

您正在修改 *(&x+4) -= 5; 中的堆栈,这是未定义的行为,在未定义的行为下,任何事情都可以发生,甚至让恶魔从您的鼻子里飞出来。参见 http://catb.org/jargon/html/N/nasal-demons.html

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