C语言程序奇怪而有趣的输出

6

我用C语言编写了以下代码:

 #include <stdio.h>
 #include <stdlib.h>

 #define LEN 100 

 int main(void) 
 {
    int arr[LEN];
    int i;

    for (i = 0; i < LEN; i++)
       printf("%d ", arr[LEN]);

    getchar();
    return 0;
 }

首先,注意我有意访问不属于数组的内存(最后一个单元格将在索引LEN-1中,但我正在访问arr[LEN]而不是arr[i])。

奇怪的结果是当我运行程序时,它打印出0到...LEN-1之间的所有数字。 例如,当LEN定义为100时,输出如下:

0 1 2 ..... 99

请运行该程序。你也遇到了这个问题吗?我认为这是与平台相关的行为。(如果相关的话,我在Windows 7上运行了此代码。)

为什么arr[LEN]的值会改变?


14
未定义行为就是未定义行为。在这种特定情况下,看起来您已禁用优化,并且'i'恰好位于'arr'结束后的下一个地址,但一般来说可能会发生任何事情(恶魔,鼻子等),这并不令人惊讶。 - Paul R
首先初始化数组,其次arr[LEN]是未定义的行为,应该是arr[i] - Grijesh Chauhan
@PaulR 哦,现在我明白了。谢谢,那显然就是答案。 - Programmer
1
我的猜测是你在数组之后直接定义了 i。因此,&arr[LEN](即 arr[100])可能恰好是 i 的地址。 - Arnaud Denoyelle
@JeremyWest 我认为人们假设 arr[LEN] 是一个错误,应该是 arr[i],然后被 downvote,并说“这不是奇怪的特定于平台的行为,你写错了代码”。我已经编辑了问题,以明确这是故意的。 - Kate Gregory
显示剩余4条评论
2个回答

7

栈是保存局部变量的地方。您的编译器在数组后面的内存位置(基本上是arr [LEN])中使用来保存i。因此,在每次迭代中,您会意外地打印出i。不同的编译器可能会将i保留在其他位置,您就看不到相同的问题。


3
为了对其他回答进行详细说明,请考虑以下内容:
代码
#include <stdio.h>
#include <stdlib.h>

#define LEN 100 

int main(void) 
{
    int i;
    int arr[LEN];

    printf("&arr[LEN]: %p\n", &arr[LEN]);
    printf("&i:        %p\n", &i);

    return 0;
}

输出

&arr[LEN]: 0x7fff5cf90a74  
&i:        0x7fff5cf90a74

在我的机器上,如果在arr之前声明了i,则iarr[LEN]具有相同的地址。

在您的机器上运行以下命令

#include <stdio.h>
#include <stdlib.h>

#define LEN 100 

int main(void) 
{
    int arr[LEN];
    int i;

    printf("&arr[LEN]: %p\n", &arr[LEN]);
    printf("&i:        %p\n", &i);

    return 0;
}

您应该看到非常类似的东西(当然地址会不同),就像我所看到的一样。


谢谢,那显然就是答案。 - Programmer
回复:“你应该会看到非常相似的东西”--请注意,您需要禁用所有优化才有可能看到类似的结果,即使这样也并不保证。 - Paul R
@PaulR 他已经配置好了类似的东西,因此才会有这个问题。 - Fiddling Bits
@FiddlingBits:我更多地考虑到这篇答案的未来读者,他们可能会得到非常不同的结果。 - Paul R
@PaulR 您说得完全正确。我应该记住这一点。 - Fiddling Bits

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接