首先来判断以下代码的执行结果

#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个字节甚至没有空档空间。所以不同编译环境下,这段代码的执行结果可能不同。

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

【C语言数组下标越界】数组下标越界引发的死循环相关推荐

  1. C语言从青铜到王者——数组详解总结【一维数组、二维数组、字符数组、数组实例】

    所谓数组,是指将那些具有相同类型的.数量有限的若干个变量通过有序的方法组织起来的一种便于使用的形式.数组属于一种构造类型,其中的变量被称为数组的元素.数组元素的类型可以是基本数据类型,也可以是特殊类型 ...

  2. 总结C语言中的数组知识点

    数组:只能存放一种数据类型,比如int类型的数组.float类型的数组,里面存放的数据称为"元素". 数组的定义: 首先声明数组的类型,然后声明数组元素的个数,也就是定义需要多少存 ...

  3. C语言 指针数组和数组指针区别 - C语言零基础入门教程

    目录 一.简介 1.数组 2.指针 3.指针和数组区别 二.指针数组和数组指针区别 1.指针数组 2.数组指针 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> ...

  4. C语言 指针和数组区别 - C语言零基础入门教程

    目录 一.前言 二.指针和数组区别 1.通过 sizeof 获取大小 a.计算数组大小 b.计算指针大小 2.指针和数组赋值方式不同 a.指针赋值 b.数组赋值 3.指针是指针变量,数组是指针常量 三 ...

  5. C语言 二维数组遍历 - C语言零基础入门教程

    目录 一.计算一维数组长度 二.计算二维数组长度 1.二维数组行数 2.二维数组列数 3.二维数组的元素个数 = 二维数组行数 * 二维数组列数 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C ...

  6. C语言 二维数组行数和列数计算 - C语言零基础入门教程

    目录 一.计算一维数组长度 二.计算二维数组长度 1.二维数组行数 2.二维数组列数 3.二维数组的元素个数 = 二维数组行数 * 二维数组列数 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C ...

  7. C语言 二维数组定义和使用 - C语言零基础入门教程

    目录 一.二维数组简介 二.定义二维数组并初始化 1.定义二维数组 2.初始化二维数组 三.访问二维数组 四.修改二维数组 五.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 & ...

  8. C语言:初识数组及数组的复制

    什么是数组?数组是由相同类型(记住是相同,不同类型不可以)的一系列数据组成.基本上C语言变量可用的类型,在数组也可使用. 数组的语法如下: 类型 数组标识[长度] ,其中数组的长度或元素个数用方括号括 ...

  9. C语言基础知识-数组和字符串

    C语言基础知识-数组和字符串 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数组概述 在程序设计中,为了方便处理数据把具有相同类型的若干变量按有序形式组织起来的方式我们称为数组 ...

  10. c语言中二维数组中维数的计算,数组指针字符串C语言程序设计-第4章.ppt

    <数组指针字符串C语言程序设计-第4章.ppt>由会员分享,可在线阅读,更多相关<数组指针字符串C语言程序设计-第4章.ppt(132页珍藏版)>请在人人文库网上搜索. 1.程 ...

最新文章

  1. HTTP请求消息数据格式分析以及request和response
  2. JS函数表达的几种写法
  3. 领导看了我写的关闭超时订单,让我出门左转!
  4. Postman中对报文进行AES+Base64加密请求
  5. milk and news paper(transfer)
  6. svn服务器搭建之备份3
  7. Miracast/WIDI浅谈
  8. 反欺骗:从黑客时代的神话说起
  9. python 音乐播放器
  10. 各地的磁倾角_全国各地区地磁场强度表
  11. java jre 配置_JRE的安装及环境变量配置
  12. python保存到txt_python保存成文本文件
  13. Function的用法
  14. python爬虫的意义_爬虫的意义与爬虫基本流程
  15. 软考最后冲刺阶段该怎么做
  16. github访问不了怎么办
  17. oracle数据表空间与数据文件,oracle的表空间及数据文件
  18. LAB颜色空间各通道的取值范围
  19. c语言写易语言支持库6,易语言编写支持库
  20. 惊呆了!我用 Python 可视化分析和预测了 2022 年 FIFA 世界杯

热门文章

  1. 3dsmaxC4DbodypainterPS画贴图三、摆放已经调节好大小比例的UV。
  2. 文件下载 之response header中获取文件名
  3. 基于Hexo的个人网站制作简明教程
  4. Spring的七种事务传播行为
  5. 项目经理、技术经理、team leader
  6. Nmap使用方法简析
  7. jquery deferred done then区别
  8. vue-cli 目录结构详细讲解
  9. crmebPro二开文档总目录结构
  10. SQL 函数YEAR MONTH 查找特定日期