初来乍到,也是第一次写博客,能与诸君共同学习交流也是极好的。
现在就贴上我们的源代码:
#include <stdio.h> int main() { int i, a[10]; for (i = 0; i <= 12; i++) { a[i] = 0; printf("Hello World!\n"); } getchar(); return 0; }
原题是问屏幕上共输出多少行 'Hello World!' 我不妨猜猜你们内心的想法:13行嘛,so easy! 但是,事实结果真的是这样吗?不妨把代码拷到你自己的机子上试验一下。结果是不是出乎意料呢?
我们看到屏幕上连续不断地打印 'Hello World!' ,一度陷入了死循环!这是为什么呢?
如图所见,内存分配基本如图所示,其他区域暂不讨论。我们平常所申请的局部变量,比如 i是向下扩展的。而数组则不同,内存分配给了它栈地址。栈是向上扩展的,就是假设我们定义了数组 a[10] ,它就变成了这样:
当我们执行for循环时,随着 i 的每次加1,我们依次修改了a[0] , . . . , a[9] , a[10] ,a[11] ,a[12]的值。然而我们发现a[10] , a[11] 和 a[12] 超出了数组 a 的边界,所以执行到 a[12] = 0 的时候,a[12] 不仅仅只是 a[12] , 我们对比它和 i 的地址会发现,它俩地址相同,即 a[12] 就是 i 。所以,每当程序执行到 i = 12 是,我们通过 a[i]=0 又把它的值改成了 0 ,所以,程序就会一直循环下去。
看到这里,也许又有人要疑问了,为什么是 12 这个数字呢?它有什么特殊含义呢?
那是因为,起初这个问题的提出是在VC++6.0 中提出来的,在VC++6.0 中这个数字就是10,a[10] 就是 i 。可见,在那里边分配给 i 和 a[ ] 的地址是紧挨着的。所以为了防止程序员的疏忽引起的数组下标越界问题,新版本的 c 标准为其地址之间预留了几个字节的间隙,(比如定义了 a[10])一旦访问到 a[10] ,那么编译器就会报错。
但是,我们的程序中为什么编译器没有报错呢?问题出在这里:因为我们程序编译的时候 a[i] 中的 i 是一个变量,它的初始值是 0 ,是正常的,等到程序运行的时候便陷入了死循环,编译器根本来不及报错,也没机会报错了。
因本人水平有限,计算机技术发展迅速,博文中难免存在疏漏、欠妥和错误之处,恳请诸君批评指正,在此表示感谢。让我们共同努力,共同提升!