此代码如何在没有任何循环语句或 '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
也许对于具有特定编译器的特定硬件,您总是会得到相同的行为,但它不需要。
以下代码不包含任何循环,或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
也许对于具有特定编译器的特定硬件,您总是会得到相同的行为,但它不需要。