【问题标题】:What's happening here in this for loop [closed]在这个 for 循环中发生了什么[关闭]
【发布时间】:2012-10-12 04:17:08
【问题描述】:

我正在尝试其他方法,但突然卡住了这个无限循环。 请提出一个答案,并解释下面的 for 循环中发生的事情

#include<stdio.h>

int main()
{
 int x=0;
 int i;
 int array[5];
 for(i=0;i<=5;i++)
 {
  array[i]=x;
  printf("#%d value set in index %d\n",x,i);
 }

 return 0;
}

当我删除=for 循环的条件下登录它工作正常。

但是当我把它放到无限循环中时,为什么? 访问数组中的额外元素(超过其限制)是未定义的行为还是什么? 任何帮助将不胜感激。 提前致谢。

~

【问题讨论】:

  • 寻求明确由于故意错误导致的未定义行为是浪费时间......你的电脑还不如飞到火星..
  • 是的,访问数组中的额外元素(超过其限制)是“未定义的行为”。它可能会在您的中显示无限循环,在另一个编译器/pc/系统中它可能会以不同的方式表现。最好不要在未定义的行为之后浪费时间,并检查您的代码并按照标准修复问题(在这种情况下,在 'for' 循环的条件下制作 'i

标签: c arrays for-loop


【解决方案1】:

i==5 时发生未定义的行为。 array 具有有效索引 0..4 - C 中的数组从 0 开始。

如果您将&lt;= 替换为&lt;,您将遍历有效索引。

访问数组中的额外元素(超过其限制)是未定义的行为还是什么?

是的。

【讨论】:

    【解决方案2】:

    您正在将 6 个整数写入一个空间为 5 的数组。第 6 次写入超出了数组的边界,因此其效果是不可预测的。在您的情况下,它写入堆栈的下一个 sizeof(int) 字节。这是用于i 的内存,循环计数器被重置为 0。

    正如您在问题中所说,解决此问题的方法是将 for 循环的 &lt;= 退出条件替换为 &lt;

    【讨论】:

    • 但是它是如何写给“i”的,你能告诉我...
    • 是的,我知道它超出了数组的限制,但想知道 i variabel 的修改
    • @Omkant 我已经更新了我的帖子以(尝试)涵盖这个
    • 表示i的地址与array[5]相同?
    【解决方案3】:

    你的 for 循环应该从 0 变为 4,因为你的数组有 5 个元素

    #include<stdio.h>
    
    int main()
    {
     int x=0;
     int i;
     int array[5];
     for(i=0;i<5;i++)
     {
      array[i]=x;
      printf("#%d value set in index %d\n",x,i);
     }
    
     return 0;
    }
    

    【讨论】:

    • 请完整阅读问题,这不是我的问题。我知道你给出的这个问题,但问题是它为什么会无限循环
    • 对不起。显然你正在溢出你的数组,这些数组有意想不到的行为,比如覆盖你的 i 变量(谁知道)。在 i==4 之后,您的 printf 在控制台上会出现什么问题?
    • 打印 5 行并循环重复
    • 如果您想自己检查,请尝试输出 printf("0x%x vs 0x%x \n", array + 6, &i) 并比较地址。
    • @user1654209 - 仅供参考,%#x 将在显示十六进制地址时保存一个步骤,它会为您打印 0x
    【解决方案4】:

    为避免轻易导致此类错误,以下是在实际(本地)数组上编写 for 循环的两条好规则:

    1. 迭代从索引 0 开始,因为 C 的数组是从 0 开始的。
    2. 始终使用&lt;。从不&lt;=
    3. 不要重复大小,让编译器使用sizeof array / sizeof *array 计算它。请注意第二项中的星号。

    所以,这个循环应该是这样写的:

    for(i = 0; i < sizeof array / sizeof *array; i++)
    

    然后你就安全了。

    请注意,这仅适用于大小对sizeof 可见的“真实”数组,如果您让数组“折叠”成一个指针,它将不起作用。

    另请注意,sizeof 不是函数,因此在此类情况下,其参数周围不需要()s。

    【讨论】:

    • 很好的解释..thanx
    【解决方案5】:

    您试图在大小为 5 的数组中存储 6 个 int 值,这是非法的。

    因此,当您尝试在数组的第 6 位写入时,您将写入变量 i,其值为 x(即 0)。 现在在您的下一次迭代中,因为 i 为 0,它小于 for 循环中指定的条件。这会导致你的循环一遍又一遍地运行!

    【讨论】:

    • 顺便说一句.. 但无论如何解释得很好,所以 +1
    【解决方案6】:

    为什么你会进入一个无限循环,在这种特定情况下,实际上很容易理解,看看你的堆栈上的地址:

    int main( ) 
    {
        int x = 0;
        int i;
        int array[5];
        printf("&x = %#x, &i = %#x, array = %#x, array+4 = %#x\n", &x, &i, array, array+4);
    

    printf() 的结果将显示变量的地址以及数组的开始和结束:

    &x = 0xbfac9cec, &i = 0xbfac9ce8, array = 0xbfac9cd4, array+4 = 0xbfac9ce4
    

    按顺序,您的堆栈如下所示:

     var        address
    ***********************
    array[0]    0xbfac9cd4
    array[1]    0xbfac9cd8
    array[2]    0xbfac9cdc
    array[3]    0xbfac9ce0
    array[4]    0xbfac9ce4
      i         0xbfac9ce8
      x         0xbfac9cec
    

    现在您的循环正在写入 0-5(6 个元素),您的数组中只有 5 个元素,因此写入第 6 个元素实际上会覆盖堆栈上的下一个内容,在这种情况下为 i。 这使得这条线:

    array[i]=x;
    

    和写这个一样:

    i = x;
    

    这会将 0(在您的情况下)存储到 i,然后重新启动循环,因此您将看到它永远循环并打印“0 存储到索引 0”,然后打印“索引 1”、2、3, 4 然后在设置i=x;时再次重启

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-12
      • 2015-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多