代码如下:
#include <stdio.h>
int main()
{
int i = 0;
int arr[] = {1,2,3,4,5,6,7,8,9,10};
for(i=0; i<=12; i++)
{
arr[i] = 0;
printf("hello bit\n");
}
return 0;
}
在VS2013开发环境调试以上的代码,解释以上代码的问题。
分析:
这个代码的结果是 死循环。
在Debug版本下,按ctrl+F5运行,会发现是死循环。
居然是死循环!!!为什么不是直接崩溃呢?既然已经越界访问了为什么还是死循环呢?
别急,下面给你好好分析:
首先,我们按F10逐句调试,同时调出监视窗口,发现执行到i=11都没问题,arr[10],arr[11]都变为0
接着按F10,发现arr[12]和i都变为0
接着执行,发现发现arr[12]和i同步变化
那么这个时候,我们就怀疑此时arr[12]和i在同一地址上。
我们调出内存窗口,从执行到i=1开始查看每次循环后i和arr[12]的地址,发现都是相同的。(地址相同)
所以当执行arr[12]=0时把i也变为0从而造成死循环没有越界报错。
那么为什么会出现这种情况呢?
1、局部变量i和arr是放在栈区内的。
2、栈区内存的使用习惯是先使用高地址再使用低地址(通俗来说,也就是先定义的变量先进去栈区,后定义的后进来,出去的话就是后定义的先出去)
3、数组元素地址是随着数组下标由低到高变化,由低地址到高地址。
【注意】
1、在vs2013-2019中,i和arr之间空2个元素。
2、在vs6.0中,i和arr之间是空0个元素。
3、在gcc中,i和arr之间空1个元素。
在这个代码中,栈区使用如下:
因为i和arr之间隔2个元素,所以当arr[9]执行完成之后,arr[10]和arr[11]依然执行,当执行arr[12]时,arr[12]覆盖i的位置,和i的地址一样,所以此时arr[12]有地方变为0,而由于i和arr[12]地址相同,所以他们同步变化,造成死循环。
【注意】
若按照此逻辑将i放在arr后定义则无死循环直接报错!
补充:
在release版本下,相同代码执行,结果如下:
原因:在release版本下,会自动对代码进行优化,避免i和arr[12]的地址相同。