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

一、笔试原题

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

程序如下图:

通过在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;
}

运行结果为:

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


调试步骤

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

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


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

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


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

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


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

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


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

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


三、解释原因

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

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

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

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

如下图所示:

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

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

VC6.0中,会空0个整型

gcc中,会空1个整型

VS2013/VS2019,会空2个整型

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

  • 33
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值