C 这个循环是如何结束的,结果是确定的吗?

C 这个循环是如何结束的,结果是确定的吗?,c,iteration,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的库名称周围放上尖括号时,代码打印不正确 #inc

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

我感到困惑的原因是:

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的库名称周围放上尖括号时,代码打印不正确

#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;
}
#包括
#包括
#包括
int main(){
int someNumber=97;
int someArray[2]={0,1};
int找到值;
for(findTheValue=0;(someNumber-=someArray[findTheValue])>0;findTheValue++){
}
printf(“疯狂值是%d”,findTheValue);
返回退出成功;
}

根据您的编译器,
someArray[2]
是指向
查找值的指针

因为这些变量是一个接一个地声明的,所以它们完全有可能在内存中连续定位(我相信是在堆栈上)。C实际上不做任何内存管理或错误检查,所以
someArray[2]
只是指
someArray[0]+2*sizeof(int)
处的内存

所以当
findTheValue
为0时,我们减去,然后当
findTheValue
为1时,我们减去1。当
找到值
为2时,我们减去
某个数字(现在是94)并退出

这一行为决不能保证。不要依赖它

编辑:someArray[2]很可能只是指向RAM中的垃圾(未指定)值。这些值可能大于93,并将导致循环退出

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

循环退出,因为(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]

这不是我第一眼看到的答案。

检查地址:

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]实际上指向某个数字


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

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


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

真的,我会猜findTheValue将=0作为输出。。。因为,当findTheValue==0时,someNumber-=someArray[findTheValue]肯定大于0…@anon:循环将继续,直到条件为False为止。它可能每次都在您的计算机上工作,但不是确定性的。仅仅因为它在运行时工作并不意味着代码是好的。这段代码读取的内存超过了数组的末尾。这是一个bug,使输出变得毫无意义。你可能会在你的机器上得到一致的输出,但代码仍然是坏的和无用的。我已经在我的计算机上运行了很多次这个程序,并且一直得到相同的输出。。。你确定吗?这也是他完全相同的输出…你可能是对的。我编辑了我的帖子。尝试在循环内打印someArray[findTheValue]的值,并告诉我们您看到了什么?下面是我一致看到的输出:-findTheValue=0和someNumber=97,someArray[findTheValue]=0和someNumber=1和someNumber=96,someArray[findTheValue]=1和someNumber=94和someArray[findTheValue]=2疯狂值是3正如我在上面回答的,循环中的第一次迭代是97-0,第二次迭代是97-1,第三次迭代是的,即使数组大小是2,它有第三次迭代,它显示我96-2,这是94,然后循环退出,显示疯狂值是3。但是对于你来说可能是一样的,但是其他编译器,其他机器,可以而且几乎肯定会给我们带来另一个价值。目前,代码中的疯狂值应该是人类期望的数组长度,但是,正如它所示,我编译了您的代码,得到了不同的结果。它不能提供可靠的答案。对不起,我没有得到你显示的结果。我使用的是ubuntu 64位gcc版本4.4.5。我用我的输出回复了Brad的回复。如您所见,someNumber-=someArray[findTheValue]的值总是设置好的,我可以在for循环退出后打印该值。正如其他人所指出的,问题是将在place数组[2]中的值实际上是随机的,因此,你可以也将得到不同的结果。你是在什么操作系统上得到上述答案的,是什么编译器?linux,gcc。如前所述,问题在于数组的第三个元素可以指向任何东西,如果你反复运行它,那么很可能会向应用程序提供相同的内存块,并且如果你可以同时运行多个副本,则会出现相同的结果(而这是一个快速的应用程序,使其更难实现)您几乎肯定会看到完全不同的结果,以及编译器如何处理数组。