C语言基础_一个错误的程序引出的知识点

今天记录一个错误的程序,原因是这个程序可以引出几个小的知识点,有助于初学者更好学习C语言。好了,直接看程序。

问题引出

#include <stdio.h>

int main()
{
	int i = 0;
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

	for (i = 0; i <= 12; i++)
	{
		arr[i] = 0;
		printf("hehe\n");
	}

	return 0;
}

看了这段代码,大家觉得运行结果是什么呢?我认为对于这段代码,90%以上的初学者都能看出代码是有问题的,很明显定义的数组只有10个元素,而在for循环里面一直可以访问到第13个元素,这是一个数组越界问题,但是如果让你说出这段代码的运行结果,我相信很多初学者会感到无法预料,我第一次看到这段代码就是这个感觉。

运行结果

直接说结果:这段代码会陷入死循环。很多人可能想不通为什么是这个结果(当然我指的是初学者)。

调试

接下来,我通过一个初学者的角度来分析一下这段代码,不想看这个可以直接跳转到结论。

第一步: 启动调试。在VS编译器中,按F10进入调试,打开监视窗口,然后添加要监视的变量iarr,因为根据for循环中的条件,一直能访问到arr[12],因此把arr[10]、arr[11]、arr[12] 也添加到监视中。如下图
图1

第二步:开始调试,按F11一步步调试,调试过程中,我们能发现一个问题,i的值与arr[12]的值保持同步,当i=12时,如下图
在这里插入图片描述

第三步:分析。我们发现,a[12] 被赋为0,i此时也变为了0,因此,无法跳出循环,这就是为什么程序运行结果为死循环的原因!

那么为什么会这样呢?这就引出了另一个知识点:数据存储,我们知道在内存中局部变量存储在栈区iarr就存在栈区。下面需要明确两个知识点:

  1. 栈区的使用方式:先使用低地址空间,再使用高地址空间
  2. 数组的存储方式:随着数组下标增长,地址由低到高变化

结论

我们先定义i放入栈中,再定义数组arr放入i下方,arr的地址是低于i的,从低到高访问数组,一旦越界,就会访问到i的地址,arr[12]的地址与i一样,指的是同一块内存! 因此当循环到i=12时,arr[12] 被赋为0,也即i被赋为0,这样的话永远也跳不出循环!如下图所示。
在这里插入图片描述

这个时候肯定很多初学者(曾经的我)会有疑问:我没定义arr[12],为什么会访问到arr[12] ? 这就又引出另外一个小知识点:关于数组的定义

我们需要知道 arr[i] 的含义,arr[i] <==>*(arr+i),所以arr[10] 这个数组也可以这样表示:10[arr]。(但必须注意不能这样定义数组,可以这样访问) arr[12] 其实就是指:地址为(arr+12)的这块内存的值 。C/C++对数组下标是不检查的,所以数组越界访问不会报错。

那么还有一个问题,i和数组arr在栈上的位置隔了两个整型空间,这是偶然还是必然?这个取决于编译器的内存分配方式,VC6.0编译器i和arr的地址是挨着的,VS空了两个整型,Linux下空了1个整型。

OK,就先写到这吧。

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值