前言:
这是我曾经遇到的一个问题,希望可以对大家有所帮助吧。
问题代码如下:
#include <stdio.h>
int main(void)
{
int i = 0;
int arr[3] = {1,2,3};
for(i=0;i<=3;i++)
{
arr[i] = 0;
printf("Hello World!\n");
}
return 0;
}
执行现象:不停地打印Hello World!
原因分析:
for的循环控制表达式一直为真,即i<=3一直成立,猜想一定是某个地方修改了变量i的值
查找错误原因的代码:
下面打印变量i和数组各元素的地址。
#include <stdio.h>
int main(void)
{
int i = 0;
int arr[3] = {1,2,3};
printf("&i = %p\n",&i);
printf("&arr[0] = %p\n",&arr[0]);
printf("&arr[1] = %p\n",&arr[1]);
printf("&arr[2] = %p\n",&arr[2]);
printf("&arr[3] = %p\n",&arr[3]);
for(i=0;i<=3;i++)
{
// arr[i] = 0;
printf("Hello World!\n");
}
return 0;
}
程序执行结果如下:
不难发现,变量i的地址与arr[3]的地址相同,所以当我们在for循环里面改变arr[3]的值时,实际就是改变了变量i的值。
那为什么arr[3]的地址就是变量i的地址呢?因为局部变量是存放在栈中的,栈的生长方向是从高到低,由于局部变量i最先定义,所以它占据较高的栈空间地址,而数组后定义,所以数组的地址比变量i的低。数组元素的地址是随着下标变大逐渐增大的,所以当我们去越界访问arr[3]时,实际是访问了变量i。
高地址 | i | a[2] | a[1] | a[0] | 低地址
避免死循环的方法:
1 先定义数组,再定义变量i。
#include <stdio.h>
int main(void)
{
// int i = 0;
int arr[3] = {1,2,3};
int i = 0;
printf("&i = %p\n",&i);
printf("&arr[0] = %p\n",&arr[0]);
printf("&arr[1] = %p\n",&arr[1]);
printf("&arr[2] = %p\n",&arr[2]);
printf("&arr[3] = %p\n",&arr[3]);
for(i=0;i<=3;i++)
{
arr[i] = 0;
printf("Hello World!\n");
}
return 0;
}
2 最最重要的是尽量避免越界访问数组。
总结:
数组越界导致死循环的原因是数组越界刚好更改了i的值。