问题代码:
#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 world\n");
}
return 0;
}
首先要先说明,不同编译器有不同的错误结果,上述代码的错误结果是博主在vs(x86)IDE上进行测评得到的, 因此若想得到和博主相同的结果,就请在vs环境下进行尝试。
说到这,一定会有人有疑问,这不就是普通的数组越界问题吗?还有什么问题?是的,数组越界就是这段代码的问题,但是,我们在日常发现越界数组时大都只是在运行结束时告诉编译器告诉你使用的数组越界,一般不会对整个程序有影响,因此,就肯定会有人觉得数组越界哪有那么危险,那么,这段代码就是通过精心设计,来告诉你越界数组到底会引发什么问题。
首先,大家觉得这段代码的运行结果是什么。打印13个hello world然后报错?不,其实这段代码的结果时死循环的打印hello world(再次声明,是在vs x86环境的debug模式下得到的结果)。
是不是觉得很神奇?接下来我们就来研究一下为什么会出现这种情况。
出现原因
内存的使用规律
首先,要想知道为什么会出现这种情况,我们首先要了解内存是如何使用的,我们要知道,内存中分为栈区,堆区和静态区,而局部变量是存放在内存的栈区位置上的,而栈区的使用是先使用高地址再使用低地址,也就是说,后创建的局部变量的地址是低于其前面创建的局部变量的地址的,有了这一个基础,就帮助我们能够更好地解释了这段代码错误的原因。
i和arr数组在内存中的位置
我们可以使用vs的调试功能,然后用监视和内存窗口观察一下各个变量的地址。
如此来看是不是就非常可观了,i和arr数组在内存中就是这样分布的。
运行过程中出现的错误
知道了这两个东西在内存中的分布后,我们再来分析这段代码,再代码的for循环中,每个arr[i]都被改为了0,这就相当于*(arr+i)被改为了0,那我们让代码走起来观察一下会出现什么结果。
现在大家终于知道越界是一件多么危险的事了把,在现实生活中,数组越界访问就像你随便使用不属于你的东西,是不是很危险,如果过于严重你是会被抓走的哦!(doge)
启发
那么,从这段代码中,我们获得了什么启发呢?首先,我们一定要避免越界访问数组,其次,我们也知道了熟悉内存的重要性,计算机界的大佬曾说过,写代码有三种境界:
- 看代码是代码
- 看代码不是代码,是内存
- 看代码还是代码
看代码是内存证明你已经知道了代码的底层逻辑,目前博主也在朝这方向努力,而如果你做到了最后一个境界,那请你一定要收我这个徒弟哈哈哈,这种境界一定是经过几百万甚至几亿行代码的洗礼才能得到的,所以,让我们大家一起努力吧!!!