【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;
}

在VS2019编译环境下,这串代码的执行结果是死循环地向控制台输出hehe。相信大家会有三个疑问:

1. 下标越界为什么不报错?
2. 每次循环执行完都会i++,迟早会不符合循环条件,为什么会死循环?
3. 这跟编译环境有什么联系?

接下来我来带着大家一起来探究其中的奥秘。

前置知识

  1. 局部变量在栈中存储,栈内存的使用习惯是先使用高地址,再使用低地址

  2. 随着数组下标的增涨,数组元素的内存地址会越来越大

#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;
}

分析这段代码,for循环的执行过程当中会给数组的每一个元素赋值,当循环执行到数组最后一个元素的下一个元素时,发生了下标越界的现象,内存中也确确实实存在着这样一块儿空间,但是这块儿空间并不属于数组本身。

栈内存的使用习惯是先使用高地址后使用低地址,意思就是随着内存空间的开辟,内存地址会越来越小。请看图:

图中一个小长方形代表一个字节。在这段代码当中,先定义了 int 类型变量 i,这会在栈区中为其开辟4个字节的内存空间。又定义了 int 类型数组arr,整个数组的内存空间将会在 i 变量所在内存空间的上方。所以通过数组下标的不断增涨,内存地址会不断增大,是有可能访问到 i 变量所在的内存空间的,在 vs2019 编译环境中,会给每个变量之间留8个字节的空隙,所以循环执行到 arr[10] 的时候,访问到了 间隙1 的内存空间,当循环执行到arr[11]的时候访问到了 间隙2 的内存空间。而当循环执行到arr[12] 时,访问的正是 i 变量所对应的内存空间,此时对arr[12]进行赋值就相当于对 i 进行赋值。当 i = 12 时,就会将 i 重新打回 0 。所以始终不会满足i > 12,也就是说循环条件始终成立,这就造成了死循环的结果。

现在来回答最开始提到的三个问题:

1. 下标越界为什么不报错?
        因为程序一直在执行,发生了死循环,报错信息根本没机会看到。


2. 每次循环执行完都会i++,迟早会不符合循环条件,为什么会死循环?
        当访问 arr[12] 时其实访问的是 i 变量,每当 i = 12 时都会给 i 重新赋值为 0,所以循环条件一直满足,循环会一直执行下去。

        
3. 这跟编译环境有什么联系?
        编译环境不同,变量与变量之间的空档空间大小不同,VS2019是8个字节,其他的可能是2个字节、1个字节甚至没有空档空间。所以不同编译环境下,这段代码的执行结果可能不同。

综上可以了解到,任何一段不符合规定的代码都有可能导致未知的结果,例如数组下标越界访问、野指针等。平时编写代码时候尽量编写符合规定的代码,规避潜在问题。

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小李哞哞

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

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

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

打赏作者

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

抵扣说明:

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

余额充值