5

应用程序的输出(底部)如下:

元素索引号:0 元素内容:22
元素索引号:1 元素内容:22
元素索引号:2 元素内容:22
元素索引号:3 元素内容:22
元素索引号:4 元素内容:22
元素索引号:22元素内容:134513712

为什么标记为 5 - 21 的索引元素会丢失?我知道由于数组的边界溢出,这段代码可能会出现段错误,它旨在做到这一点,我对为什么这段代码不好,只是为什么跳过某些索引不感兴趣。

#include <stdio.h>
int main(){

    int array[5];

    int i;
    for(i=0; i<10; ++i) {
        array[i] = 22;
        printf("Element index number: %d Element contents: %d\n", i, array[i]);
    }
    return 0;
}
4

5 回答 5

9

一旦溢出分配的内存,您就处于“未定义的区域”。可能数组写入写入了“i”存储在堆栈上的位置。

请注意,与 Java 和 C# 等语言不同,C 不进行运行时边界检查,因此当您超出数组或字符串或分配的内存时,不能保证执行任何有用的操作(如 segfault)。不能保证做任何事情。它可能会崩溃,它可能会继续运行,它可能会导致恶魔飞出你的鼻子

于 2009-06-01T18:18:47.940 回答
7

发生的事情是,当您写入数组 [5] 时,您正在写入 i。它们在内存中与堆栈相邻,因此这是您可以预期的行为。

这样想,你做了一个有 5 个元素的数组

int array[5];

实际上,数组只是一个地址。[] 中的数字指定要访问该地址多远。所以:

  • 数组 [0] 内存中过去地址“数组”的 0 个整数
  • array[1] 是内存中过去地址“array”的 1 个 int ...
  • array[4] 是内存中过去地址“array”的 4 个整数(您为数组保留的最后一个整数)

因此,如果您一路走来:

  • array[5] 是内存中过去地址“array”的 5 个整数

在 C 中没有自动边界检查,所以很高兴覆盖你自己的记忆。您在堆栈中的数组 [5] 之后放置了“i”,很可能数组 [5] 是 i。

您只需将 array[5] 或i设置为 22,因此i是 22。现在i是 22,您的下一次查找到 array[i] 实际上是 array[22]。这会抓取内存中该位置的任何垃圾,或者,如果幸运的话,会崩溃。

于 2009-06-01T18:19:00.497 回答
2

@Doug 有,但让我们稍微扩展一下。

您将 array[5] 和 i 作为自动变量,因此它们在入口处分配在堆栈上,因此您分配了 6 个单元:array[0]、array[1]、... array[4],然后是 i .

当您将 i 设置为 5 时,array[i] 指向堆栈中包含 i 的单元格。然后,您将 22 分配给它。所以现在 i=22,就像你打印的那样。

然后你得到array[i] 或array[22],它在stck 的末尾;那里的随机值恰好是那个大数字。

于 2009-06-01T18:26:12.343 回答
0

很可能局部变量“i”的存储位于堆栈上“array”之后,因此 &array[5] == &i,这意味着当您将 22 分配给 array[5] 时,您将 22 分配给“i”。

于 2009-06-01T18:20:43.647 回答
-1

您已经声明了一个包含 5 个整数的数组,但您的 for 循环将值写入 10 个条目。

改变

int array[5];

int array[10];
于 2009-06-01T18:23:43.453 回答