什么是数组越界?数组越界有什么后果?_C语言数组越界导致无限循环

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

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

51d10db4cbaf7625d7c53fbe148c0514.png

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

代码如下:

#include "stdio.h"

int main()
{
	int a[10] , i;
	
	for(i = 1;i<= 10;i++){
		a[i] = 0;
		printf("%d %dn",i,a[i]);
	}	
	
	return 0;
}

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

66437b79c02ece08603ba102ef57da84.png

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

评论如下

2861d2411a20832b93105ac75878f4eb.png

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

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

dc9e8936e0c60a5ffeba42ccea9ef20b.png

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

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

0fb008d75f46d007bfeda89503a7c12c.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 %dn",i,a[i]);
	}	
	
	return 0;
}

045099b8550b097071dc97f3bafdd7e9.png

看看内存分布

3adfb99dc2205b21926a191d3a9bb0c7.png

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

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

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

4266ebbee0dde7ba462314db1aa24929.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 %pn",i,a[i],&i,&a[i]);
	}	
	
	return 0;
}

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

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

#include <stdio.h>

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=%prn",a, &a[10],&i,&a[-1],&a[-2],&j);
	
	return 0;
}

1e3ea221c18f94a094f638f7862cac6e.png
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值