某厂校招一道关于C的笔试题

一、笔试原题

题目:在Linux  x86 _ 54   gcc环境下,下面的程序会出现什么问题?运行结果是什么?为什么?

程序如下图:

某厂校招一道关于C的笔试题_第1张图片

通过在gcc的环境下编译运行,发现运行结果为不断死循环打印0-17的数字

我们可以看到这段代码很明显有数组访问越界的问题,但理论上说当 i==18后,进入循环的条件不满足,理应会停止循环,为何会产生死循环的结果那?


 二、探讨原因

我们先看一段在VS2019编译环境下的代码的运行结果:

代码如下:

int main() {
	int i;
	int arr[10];
	
	for (i = 0; i <= 12; i++)
	{
		arr[i] = 0;
		printf("%d",i);

	}
	return 0;
}

运行结果为:

某厂校招一道关于C的笔试题_第2张图片

可以看到,结果也是同样的死循环,两段代码虽然不同但有共同之处,我们对这段代码进行调试寻找答案:(关于调试技巧,可以查看博主这篇文章实用编程调试技巧)


调试步骤

这是数组临界 i==15 时的变量信息:

某厂校招一道关于C的笔试题_第3张图片

 此时一切正常,arr[16]与[17]因为越界被赋予随机值


当数组越界 i==16、i==17时的变量信息:

某厂校招一道关于C的笔试题_第4张图片

 我们发现虽然越界了,但是arr[16]、arr[17]的值竟然也被赋值为0,因为我们大胆推测arr[18],应该也是初值为随机值,执行一次循环体后被赋值为18


在调试监视窗口加入arr[18]的信息:

某厂校招一道关于C的笔试题_第5张图片

但是事情并不像我们所想的那样,arr[18]的初值并不是随机值,而是等于17,与i相等,为了验证不是巧合,我们修改值再做比较(同样是循环体条件的数值和数组大小值差2)


修改相关值验证上方arr[18]=i不是巧合:

某厂校招一道关于C的笔试题_第6张图片

发现这段代码arr[12]也=i,所以这不是巧合


找到代码中死循环的触发原因:

某厂校招一道关于C的笔试题_第7张图片

当给arr[18]赋值为0时,i的值也相应改为0,因为可以再次满足循环条件,重复执行循环语句


三、解释原因

 arr[18]和i的值共同改变,可以推测出二者应该是在内存中占用了同一个地址

通过查阅相关资料后我们明白:

1、i和arr是局部变量,局部变量是放在栈区上的,而栈区内存的使用习惯是先使用高地址空间,再使用低地址空间

2、数组随着下标的增长地址由低到高变化

如下图所示:

某厂校招一道关于C的笔试题_第8张图片

如果i存放的地址每次都与数组最后一个元素的地址差2个空间,那么就会造成VS2019编译环境下的那段代码造成死循环。

而每次都差2个空间并不是巧合,是因为不同编译环境下i存放的地址与arr相差多少空间是固定的(由编译器自己设定):

VC6.0中,会空0个整型

gcc中,会空1个整型

VS2013/VS2019,会空2个整型

而原题是在gcc的环境中编译运行代码,i的地址与a的地址间会空一个长整型,造成死循环(原因与上方VS2019中的代码完全类似):

某厂校招一道关于C的笔试题_第9张图片

你可能感兴趣的:(C语言相关技术贴,c语言,学习,开发语言,数据结构)