文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2024-12-02 01:25

关注

引言

最近在查一个bug,查到最后发现是数组越界导致的。数组只有30个字节,代码却向这个数组填充了35个数据,这个bug还是偶现的,查到它确实废了一番功夫。我就突然想到:C语言为什么不检查数组下标呢???先来个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语言为什么不检查数组下标???答案一个字:快。

来源:知晓编程内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯