我发现了一些代码,我对于循环如何退出以及它是如何工作感到困惑。该程序是否产生确定性输出?
我感到困惑的原因是:
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;
}
答案 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,结果总是相似的。