这个循环如何结束并且结果是确定性的?

时间:2011-04-16 06:16:24

标签: c iteration

我发现了一些代码,我对于循环如何退出以及它是如何工作感到困惑。该程序是否产生确定性输出?

我感到困惑的原因是:

1. `someArray` is of size 2, but clearly, the loop goes till size 3,
2. The value is deterministic and it always exits `someNumber` reaches 4

有人可以解释一下这是怎么回事吗?

当我在包含的库名称周围添加尖括号<>时,代码打印不正确。

#include <stdlib.h>
#include <time.h>
#include <stdio.h>

int main() {
    int someNumber = 97;
    int someArray[2] = {0,1};
    int findTheValue;

    for (findTheValue=0; (someNumber -= someArray[findTheValue]) >0; findTheValue++) {

    }
        printf("The crazy value is %d", findTheValue);
    return EXIT_SUCCESS;
}

4 个答案:

答案 0 :(得分:2)

访问超出其边界的数组元素是未定义的行为。也就是说,该程序可以随心所欲地做任何事情,回复42,吃掉你的硬盘或花掉你所有的钱。换句话说,在这种情况下发生的事情完全取决于平台。它看起来可能是“确定性的”,但这只是因为你很幸运,也可能因为你只是从那个地方读书而不是写信给它。

这种代码很糟糕。不要那样做。

答案 1 :(得分:1)

根据您的编译器,someArray[2]是指向findTheValue

的指针

因为这些变量是一个接一个地声明的,所以它们完全可能连续定位在内存中(我相信堆栈)。 C并不真正进行任何内存管理或错误检查,因此someArray[2]仅表示someArray[0] + 2 * sizeof(int)处的内存。

因此当findTheValue为0时,我们减去,然后当findTheValue为1时,我们减去1.当findTheValue为2时,我们减去someNumber(现在是94)并退出。

此行为无法保证。不要依赖它!

编辑:someArray [2]可能更有可能指向RAM中的垃圾(未指定)值。这些值可能超过93,并会导致循环退出。

EDIT2:或者someArray[2]someArray[3]可能是较大的负数,减去两者会导致someNumber翻转为负数。

答案 2 :(得分:1)

循环退出是因为(someNumber - = someArray [findTheValue])没有设置。

添加调试行,您可以看到

value 0 number 97 array 0
value 1 number 96 array 1
value 2 number 1208148276 array -1208148180

即打印出findTheValue,someNumber,someArray [findTheValue]

这不是我乍看之下的预期答案。

答案 3 :(得分:0)

检查地址:

printf("&someNumber =   %p\n", &someNumber);
printf("&someArray[0] = %p\n", &someArray[0]);
printf("&someArray[1] = %p\n", &someArray[1]);
printf("&findTheValue = %p\n", &findTheValue);

给出了这个输出:

&someNumber =   0xbfc78e5c
&someArray[0] = 0xbfc78e50
&someArray[1] = 0xbfc78e54
&findTheValue = 0xbfc78e58

似乎由于某种原因,编译器将数组放在堆栈区域的开头,然后是下面声明的变量,然后是声明它们的顺序。因此someArray [3]有效地指向someNumber。

我真的不知道原因,但我在Ubuntu 32位和Visual Studio上尝试使用和不使用优化的gcc,结果总是相似的。