您的位置 首页 java

C语言为什么不检查数组下标?

引 言

最近在查一个bug,查到最后发现是数组越界导致的。数组只有30个字节,代码却向这个数组填充了35个数据,这个bug还是偶现的,查到它确实废了一番功夫……

于是我就突然想到: C语言 为什么不检查数组下标呢?

嵌入式物联网需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!

无偿分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!某鱼上买估计至少要好几十。

点击这里找小助理0元领取:

我们先来个demo验证下:

 # include <stdio.h>
#include<stdlib.h>


int main()
{
    int data[5]={0};
    for(int i=0;i<8;++i)
    {
        printf("%d ",data[i]);
    }
    printf("\n");


    return 0;
}  

结果显示,C语言还真的不检查数组的下标。不仅没有报错,而且运行正常。

思 考

这就让我陷入了思考,C语言为什么不检查下标呢?想上文这么简单的,data数据组就5个数据,编译器是知道的,为什么是访问第8个数据时,编译器来个报错也没有呢?

后来,我想到了之前的文章《指针与数组》中有如下示例代码:

  void  main()
{
    int data[4] = {0, 1, 2, 3};
    int *p;
    p = data +2;
    printf("p[-1] is %d\n",p[-1]);
    printf("*(p-1) is %d\n",*(p-1));
}  

运行结果如下:

不仅可以编译通过,还能正确的输出结果为1。这表明, C的下标引用和间接访问表达式是一样的。

这让我突然意识到,数组的这些特性,如数组名本质上是一个常量指针(不懂的同学看之前的推文《指针与数组》)C语言很难检查下标合法性的。

如果C语言检查数组是否越界,因为当数组出现在表达式中的时候,它会立刻被解读成指针。此外,使用其他的指针变量也可以指向数组的任意元素,并且这个指针可以随意进行加减运算。引用数组元素的时候,虽然你可以写成a[i],但是它只不过是*(a+i)的一种表达,C语言本身的语法是无法检查的,只能通过编译器检查。

那么编译器将加入额外的代码用于检测数组是否越界,C的下标检查所涉及的开销比你开始想象的要多。编译器必须在程序中插入指令,证实下标的结果所引用的元素和指针表达式所指向的元素属于同一个数组,可能仅仅是个小功能,生成的程序的数组检查占有大量的代码空间,这必将影响程序的运行效率。

这也让我意识到一个事情:数组的标识符(也就是数组名),它只包含并没有包含数组的长度的信息,它只是个地址信息,也就是上面说的数组名本质上是个常量指针。

读到这里,请各位想一下,C语言有提供数组长度的底层函数吗?

答案是否定的,一般情况下,我们获取一个数组的长度,我们可以获取数组所占的内存大小,然后除以单个元素的内存大小计算数组长度。

 int a[8];
 printf ("%d",sizeof(a)/sizeof(a[0]));  

为何不修复“漏洞”

既然我们发现了上述问题,那么,那些C语言的大神为什么不修复这个“漏洞”呢?其他编程语言会吸取“教训”吗?

学过 JAVA 的同学可以看看下面的代码:

 int [][] array = {{1,2,3},{1,4}};
System.out.println(array[1][2]);  

这也是一个数组越界访问的例子,但是JAVA的控制台会打印如下信息

Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 2

at demo.Array.main(Array.java:31)

会明确告诉你数组下标越界了,是的,高级语言JAVA是支持的。

那么我们就来讲讲C语言的设计目标:提供一种能以 简易的方式编译、处理低级存储器、仅产生少量的机器码,以及不需要任何运行环境支持便能运行的编程语言。

如果C语言加入了类似下标检查,实现一个简单的数组数据写入,需要大量指令检查下标是否正确,那么还符合C语言设计目标吗?如果C语言有大量的这样设计,操作系统内核还会使用C语言编写吗? 单片机 等实时系统还会使用C语言吗?

所以,C语言给了 程序员 更大空间。 C语言执行效率高,可以直接访问硬件,具有非常好的可移植性, 所以, 世界上绝大部分的操作系统内核都是用C语言编写的。

那么问题来了,JAVA都检查了数组下标,C语言难道一点进步也没有吗?其实也不然, 微软 在这一方面也做了贡献。

在早期的CRT函数中也不对 字符串 指针或数组进行越界检查,都是要求程序员确保空间足够,因此也才也才有了在VS2005之后微软提供的 安全的CRT函数 版本。(CRT函数不是本文的重点,不懂的同学请面向 百度 编程)。

总 结

C语言为什么不检查数组下标?

答案一个字: 快!

END

版权申明:本文来源于网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。

文章来源:智云一二三科技

文章标题:C语言为什么不检查数组下标?

文章地址:https://www.zhihuclub.com/195535.shtml

关于作者: 智云科技

热门文章

网站地图