Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
数组下标越界是编译哪个阶段被检测出来的_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. 这跟编译环境有什么联系?
接下来我来带着大家一起来探究其中的奥秘。
前置知识
局部变量在栈中存储,栈内存的使用习惯是先使用高地址,再使用低地址
随着数组下标的增涨,数组元素的内存地址会越来越大
#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个字节甚至没有空档空间。所以不同编译环境下,这段代码的执行结果可能不同。
综上可以了解到,任何一段不符合规定的代码都有可能导致未知的结果,例如数组下标越界访问、野指针等。平时编写代码时候尽量编写符合规定的代码,规避潜在问题。
今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
上一篇
已是最后文章
下一篇
已是最新文章