浅析一道有趣的数组题

Posted JT_GUO

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅析一道有趣的数组题相关的知识,希望对你有一定的参考价值。

浅析一道有趣的数组题

题目描述

对于一个共有10个整型元素的数组,从首元素开始,从前往后循环遍历,修改元素的值,打印字符串。

#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;
}

运行结果

对于这个题目,咋一看给人的直觉就是执行13次循环,打印13次hello world;当然也有可能是这样一种结果:由于数组越界访问,所以将arr[9]的值改为0后,系统报错,没法运行,连调试都过不去。

然而,令人震惊的是,在VS 2013编译环境下,编译器竟然没有报错,运行起来了!运行的结果出乎意料,竟是疯狂打印hello world,死循环!!!

结果分析与讨论

下面由小涛给大家简单分析一波:

  • 在C语言中,内存主要可以划分为:栈区,堆区,静态区等部分。

  • 对于局部变量和数组,是在内存中的栈区开辟的。

  • 栈区的使用特点是:先使用高地址空间,再使用低地址空间。

    ​ 在这个案例中,由于先创建的是i变量,然后才是创建数组arr,故i的地址要比arr数组高。在VS 2013环境下,其内存开辟空间如下图所示(注意i的地址):

  • 对于数组而言,其存储和空间的关系是:随着元素下标的增加,对应元素的地址也是由高到低变化的。

    ​ 在此10个整型元素的数组arr中,arr[0]的地址最低,arr[9]的地址最低。

为什么运行的结果会是死循环呢?有必要对各数的地址进行探究一番。前面我们得到i的地址是0x010FFCD8,下面通过调试,对其他数据的地址查看如下:

我们惊人的发现:arr[12]位置的地址也是0x010FFCD8,这意味着什么?这不是就是说arr[12]和i放在内存中的同一个地址吗?如果把arr[12]的内容修改就会造成i的值被修改!结合我们得到的运行结果,这不是就能解释了嘛。

当i =12时,执行arr[12] = 0指令后,i也被修改成0了;判断条件i<=12恒成立,于是并没有结束循环,继续i = 0,1,2,3,4,5,6,7,8,9,10,11,12,0,1,2·····于是乎持续输出打印。

  • 有一点需要注意,不同编译环境下,i和arr的空间间隔不一定是差3字节,亲测发现gcc编译器就不是这样的分布。

哈哈,破案了~~

狄大人对这波分析很是赞同啊,元芳也表示很佩服!哈哈~~

涨姿势咯,希望小伙伴们都有get到哦!

以上是关于浅析一道有趣的数组题的主要内容,如果未能解决你的问题,请参考以下文章

奇妙JS代码系列一道有趣的题(创建一个长度为x数组)

一道有趣的签到题

一道题浅析 i++,++i,i+1及(引用)&i的区别

一道经典面试题:字符串在Java中如何通过“引用”传递

一道容易栽坑的有趣的面试题(关于js,定时器,闭包等)

一道有趣的面试题