C陷阱和缺陷

        在C语言中,那些容易让萌新犯错的特性,也正是编程大佬们为之吸引的特性。

        比方说 '=' 和 '==' ,你肯定知道一个是赋值一个是判断是否等于,你也知道什么时候要用什么符号,但是~!!!可能因为手误,少打一个,或者多打一个。

        这时你如果要是问大佬我要如何避免这个问题,他可能给你两个答案:1. 认真敲代码! 2. 当你想用 '==' 的时候,把判断的条件放在左边,变量放在右边。

        这么一看肯定是2更加有效,毕竟大部分都是很认真在敲,但是还是会疏忽,虽然你这么记了,但是到真打的时候,你可能还会忘~

        类似这个错误的还有很多,因为这样不是语法错误,他可以正常编译过去,但是它展示出来的效果不是你想要的效果,当然这个代码就有问题,这种问题是很让人头大的。接下来我要给大家解析一个很经典的题型供大家学习。


        首先我们先看这段代码,你们先看看有什么问题。可不可以运行起来,如果可以运行起来,那么运行的结果是什么呢?

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("hehe\n");
    }
    return 0;
}

        我们先能看到的就是arr这个数组里只有10个元素,但是for循环遍历的时候访问了13个元素,首先想到的会不会是对数组遍历的时候越界访问了呢?

        答案是肯定的,确实是越界访问了。我在x64下运行不起来,它会出现如下图片的错误:

         但是在x86下可以正常运行,运行的结果就是一直打印 'hehe' 死循环,这个结果是不是出乎意料,难道越界访问不就是遍不过去了么,为什么还会打印,还是死循环打印 'hehe' ,接下来我就来分析分析~!

        首先我们要先对数组和局部变量的在栈区的存放方式,如下图所示:

 

         当我们了解上图的存储方式后,我们就可以顺利的分析了。

        我们先对这个代码进行调试,因为调试可以看出问题所在。接下来我会给大家展示一步一步的调试,让大家看清楚出处。

        开始没进行初始化的时候,数组里的数都是随机值,如下图所示:

 

        然后对其进行初始化:

        然后我们通过for循环遍历arr数组里的数值:

         如此循环后我们从0~9全遍历一遍,arr[0]~arr[9]全赋值为0,此时i遍历到了9:

 

        然后我们接下来再遍历就会产生越界访问了,当然在调试的时候是可以看到的,确实将不属于自己的空间赋值为0了。 

 

         接下来重点来了!!!

         接下来我们继续调试:

        这时候就已经很奇怪了,明明是i++,还没有对arr[12]进行操作,arr[12]为什么会改变呢,而且是和i的值是相同的,我们继续来调试:        

         诶,这不对啊,为什么将arr[12]赋值为0了以后i也跟着变为0了呢?这时候问题已经彻底显现出来了,i改变arr[12]也会跟着改变,相同arr[12]改变,i也跟着改变。那么这是为什么呢?

        这时候我们开始的那张图就很重要了:

         这里就可以观察到,如果以这种方式存放i和数组arr时,arr[12]和i就是同一个地方,当然一个地方肯定不可能用两个不同的方式表现,这里的arr[12]是越界过来的。

        那么真实情况是不是这么存放的呢?我们继续观察:

         所以事实就是这么存放的,当将arr[12]赋值为0的时候,也就是i赋值为0了,那么这个循环就会一直下去,成为死循环,你的屏幕上也就会一直打印 'hehe' ~


        到这里我已经讲完了,你们肯定也听懂为什么这样了,其实不同编译器的存放方式不一样,我用的是2022是这样的。

        当然这里如果定义i的时候放在定义数组的后面也就是:

         这样arr[12]和i就不会指向一个空间,当然这样数组越界访问会产生错误,那么你可能会想,为什么第一种也越界了,还可以死循环的打印 'hehe' 呢,其实我是认为编译器忙着去打印 'hehe' 去了,编译器都忙的不行,哪管得到越界访问的问题~

        到这里已经给大家详细讲解了这道题,讲解不易,麻烦各位看官给作者点个赞吧,让我看到创作的动力,谢谢你们~!!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NPC Online

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值