【问题标题】:How This Code Loops Without Any Loop Statement or 'goto' or Recursion? [closed]此代码如何在没有任何循环语句或“goto”或递归的情况下循环? [关闭]
【发布时间】:2019-06-16 15:49:11
【问题描述】:

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

这个神秘的代码*(&amp;x+4) -= 5; 导致了循环。


据我所知,x 的值被保存在堆栈内存中。可能是这样,在(&amp;x+4)之前有函数foo的指针,而foo正在被递归调用。

再说一次,我不确定我的假设是否正确。我也不明白5 来自哪里。我试图打印和分析函数指针和变量的地址(由我的同事建议);并将它们与我对C memory layout 的了解相匹配。但我更困惑了。


如果在x 前后声明了更多变量,*(&amp;x+4) -= 5; 会如何变化?


操作系统: Windows-7 64 位,编译器: GNU GCC,编辑器: CodeBlocks 16.01

【问题讨论】:

  • 它只打印1然后退出。
  • 这取决于未定义的行为。当x 只是int x 时,您不应该取消引用(&amp;x+4) 的内存。
  • @SouravGhosh 我在网上找到了代码。我知道-我不应该那样编码。我只是想知道解释
  • 依赖堆栈布局和硬件架构细节的自修改代码。如果没有提供这些细节,这个问题是没有用的。前任在我的 Fedora 29 x86_64 和 gcc 8.2.1 上,我只遇到分段错误。老实说,那里没有错误惊喜......
  • @StefanBecker 这不是“自修改代码”,它只是破坏了自己的堆栈。

标签: c++ c loops undefined-behavior


【解决方案1】:

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

您的平台上可能发生的情况是,它可能最终会修改它返回的地址,导致它在调用foo 之前返回到main,导致main 再次调用foo .

【讨论】:

  • 代码不是有效的 C 或 C++ 并不一定意味着它有问题。如果它附带说明要使用特定版本的 GCC for Windows 7 进行编译,那么它取决于编译器的行为。它甚至可能不是无证行为。
  • 我从未见过任何类似的编译器文档。如果它依赖于未记录的行为,那就是错误的。无法知道行为会在什么条件下发生或不发生。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2018-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-06
      • 2018-03-14
      • 2021-06-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多