2014-10-01 140 views
-8

此处数组的下标超出范围。超出范围的下标

int a[10], i; 
for (i = 1; i <= 10; i++) 
a[i] = 0; 
printf("India"); 

输出是一个无限循环并且printf语句不会被执行。这里是写在K N王的东西:

当我达到10时,程序将0存储到[10]中。但是[10]不存在。 因此0在[9]之后立即进入内存。如果变量i碰巧在内存中遵循 a [9](可能是这种情况),那么我将重置为O.导致 循环重新开始。

任何人都可以解释它吗?

+5

数组索引是基于**零**的,即在你的例子中,0到9,而不是1到10. – isedev 2014-10-01 15:31:20

+0

为什么它是无限循环 – 2014-10-01 15:32:34

+0

告诉我原因 – 2014-10-01 15:34:57

回答

3

这将形成一个无限循环的想法是基于一个关于如何将变量放置在内存中的假设。特别是,它假定因为i定义为之后立即在a之后,它也会在a之后立即分配到内存中。

这当然不能保证,但它同样肯定会发生。如果是,则写入a[10]实际上可能会覆盖i。由于它将0写入不存在的a[10],因此实际上将0写入i。然后当循环中的条件检查i <= 10时,这是真的,因此循环继续 - 并且每次i变为10时,在之前它立即被0 覆盖,因此循环条件被评估,所以循环从开始。

就C或C++标准而言,它只是未定义的行为 - 当代码写入数组末尾时任何东西都可能发生。它可能会做某人期望的事情,或者可能会做一些完全不同的和不相关的东西,完全不会有意义。编译器可以自由发出在这种情况下几乎完成任何事情的代码(或者它可以将它诊断为错误,并且根本不会发出任何代码)。

给什么符合行为可能是一些想法:GCC的早期版本有代码来检测的实现定义的特定情况下(非常喜欢不确定的行为,除了实施必须以文件它做什么) 。在这种情况下,记录的行为相当复杂。编译器将尝试做以下每一项为了(在那个成功的第一个停止):

  1. 运行nethack(游戏)
  2. 运行流氓(另一场比赛)
  3. 启动Emacs,并让它执行河内模拟的塔楼
  4. 打印出“你正处在一个曲折的小段落的迷宫中,都一样”。

我可以得到这些有点不对的顺序(这是一个很长时间前),但你的想法。结果有什么也没有与一个合理的人可能会期望的任何事情。

+0

+1对于各种UB尤其是“你正处在一个曲折的小段落迷宫中,一切都一样”。嗯,一个空洞的声音说“Plugh”。 – chux 2014-10-01 17:40:20