回顾上文:
一个有问题的代码
int main() { int i = 0; int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; for (i = 0; i <=12; i++) { arr[i] = 0; printf("hehe\n"); } return 0; } 复制代码
执行结果:死循环打印hehe
为了发现问题:打印第几次打印
int main() { int i = 0; int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; for (i = 0; i <=12; i++) { arr[i] = 0; printf("hehe\n"); printf("第%d次打印\n",i); } return 0; } 复制代码
i不能变为12
调试结果:
将第数组元素下标为12的值也改成0时,i也恢复为0,所以造成了死循环
**为什么呢?
猜想两个占用同一块空间
->验证
深入理解上述程序err原因
栈区先使用高地址,再使用低地址. 先定义变量i,所以i在高地址位置,然后再定义数组,二者相隔几个地址未知
arr和i中隔了几个元素是未知的,取决于编译器
变量和数组相隔距离
VC6.0中: arr和i是紧挨着的 VS2013-VS2019 arr和i中间有两个元素 gcc: arr和i之间放一个元素 复制代码
所以在VC6.0条件下,arr[10],写成i <= 10时就死循环了
如何解释:
i和arr是局部变量,放在栈区,栈区的使用习惯是先使用高地址,再使用低地址 画出栈区内存,上面低地址,下面高地址,先把高地址的空间使用了 i在下面创建,arr在上面创建, 又因为随着数组下标的增长,元素的地址又低到高变化 随着数组下标的越界访问,就可能覆盖循环变量i(二者占用同一块空间) 复制代码
问:当i和arr的创建反过来时:直接报错,不会死循环
因为内存布局发生变化
int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int i = 0; for (i = 0; i <=12; i++) { arr[i] = 0; printf("hehe\n"); printf("第%d次打印\n",i); } return 0; } 复制代码
执行结果:报错
注意
程序越界有一个报错的时间点,程序停下来时才报错,死循环了没时间报错
若改成release版本:
执行结果:打印13个hehe
在Debug情况下: i确实在数组后面存放, i的地址比数组地址大
而在Release版本:数组的地址更大 编译器进行了优化了,因为考虑到放后面可能出错
这也证明了Release版本确实可以优化