linux for循环_C语言数组越界导致无限循环

昨天晚上,我正在给之前获奖的同学发奖品,正在进行中的时候,看到黄兄推送了一篇文章,里面讲到数组越界会导致无限循环。

关于抽奖看这篇文章《Linux进程管理数据结构》,以后也会不定期抽奖,今年多赚点钱,过年的时候,希望给大家抽一个大奖,喜欢的读者使劲给转发点赞,关注,未来是你们的,大奖也是你们的,感谢支持,不喜欢的请轻拍。过年抽奖我还是很期待的,每年公司的年会抽奖的时候,我总是能小中一把,有一年我还中了个一等奖,不知道大家对一等奖什么概念,中一等奖的概率非常低,集人品运气于一身的,我当时酝酿了全宇宙的力量,不说了,发功的时候真的非常累。

57afa568136274c402b8b3b95372fb7c.png

就是这个截图,我看了下,感觉有点意思,赶紧就自己敲下代码看看是怎么回事,可惜的是,我怎么也没看到出现无限循环啊。

代码如下:

#include "stdio.h"

int main()
{
int a[10] , i;

for(i = 1;i<= 10;i++){
a[i] = 0;
printf("%d %d\n",i,a[i]);
}

return 0;
}

我先是在 dev c++ 上面试了下,结果如下e81070f54fea605f86d9bc0f810624b1.png

我这时候想,黄兄是不是忽悠我了,我要去成都叫他请我吃饭,然后我就给他评论

评论如下70233832ac1e998bd3944e6b447834de.png

竟然还有人给我的评论点赞了,啊啊啊啊啊啊~

不死心,赶紧又到Linux 下用 gcc编译 结果如下f0cecb0c91d1aa2e9e1aa4ac63e4b594.png

还是没有无线循环,我要死了,要是在群里面讨论这个,我要是说不出来会不会丢脸一个晚上。

赶紧用大招,看看i的地址和a[i] 的地址

1adfa88a4d83450399a90c1467101984.png

看这个图,i等于 10的时候, &a[10] 的地址和 i的地址还是独立的,虽然 a[10]已经超过了 数组的范围,但是并没有对i造成任何影响。

然后,我脑子一响,突然顿悟发现这个代码的问题所在了,这个数组越界没有越过去,要是越过去了,侵犯了i的领土「内存地址」了肯定就死循环了。

代码修改一下

#include "stdio.h"

int main()
{
int a[10] , i;

for(i = 1;i<= 12;i++){
a[i] = 0;
printf("%d %d\n",i,a[i]);
}

return 0;
}
f4724279647d819ec7d4e36c0b004af7.png你看,你看,这样一越界过去,就产生了死循环,i一直都是0,怎么也跳不出for循环了。

看看内存分布e215905a6f8cc3de8eb0be1fbb9b298d.png上图中 i = 10的时候,&a[10] 还没有越界到 &i「i的地址」,等下一次循环 i = 11的时候,那 &a[11]  就等于 &i 了,a[11] = 0,其实也就是 i= 0,死循环也就是这样来了。

从这个例子我们可以明白一点,为什么数组不能越界操作了没?如果真的是项目里面的代码,要是编译器也不给出提示,那么你即将构造一个非常难排查的bug出来。

如果对上面的地址还是不感冒,可以看看这个图片

95619dbcf627151b763a23fe7d9d3cbd.png

a我们定义的是10的大小,但是我们使用 a[10],这个是越界操作,越界操作编译器不会提示编译出错,但是这样操作就可能侵犯到i的地址,实际上把i给赋值了,所以会导致i=0,一直跳不出for循环。

我们正常一个数组遍历会这样写

#include "stdio.h"

int main()
{
int i;
int a[10];

for(i = 0;i < sizeof(a)/sizeof(a[0]);i++){
a[i] = 0;
printf("%d %d %p %p\n",i,a[i],&i,&a[i]);
}

return 0;
}

编译器就好像法律,约束着人们的行为,但是有些法律没有涉及到的,就很容易被打擦边球。

最后用这个代码看看内存的增长「一个读者奉献的」

#include 
int main(void)
{
#pragma pack (4)
int j;
int a[10];
int i;
#pragma pack()
printf("a=%p &a[10]=%p &i=%p &a[-1]=%p &a[-2]=%p &j=%p\r\n",a, &a[10],&i,&a[-1],&a[-2],&j);
return 0;
}

659321782f7c78434564b594468c7081.png


53f79689e2b7a0a5eff5609711b0ca26.png 扫码或长按关注 回复「  加群  」进入技术群聊
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值