IT业界:神奇的C语言:一段令人百思不得其解的代码

    作者:python君2020-05-11 14:46:45

    C语言是一门面向过程的计算机编程语言,与C++、java等面向对象编程语言有所不同。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、仅产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。C语言描述问题比汇编语言迅速、工作量小、可读性好、易于调试、修改和移植,而代码质量与汇编语言相当。C语言一般只比汇编语言代码生成的目标程序效率低10%~20%。因此,C语言可以编写系统软件。

    今天在翻阅头条时,无意看到这样一篇微头条,说是作者的同事在工作中遇到一个BUG,两人一起研究了大半天,非但没有解决问题,反而一起陷入了郁闷,甚至三观尽毁!

    他没有说具体过程,在简化了问题后,是这样一个代码(我增加了一条打印地址的代码):

    #include

     

     

    int main (int argc,char*argv[])

     

    {

     

         int a[5]={0,1,2,3,4};

     

      	 int b=3;

     

     

      	printf("%d,%d",a[b],b[a]};

     

        printf("%d,%d\\n",&a[b],&b[a]);

     

     

     

        return 0;

     

         }

     

    这个程序看上去蛮简单的,我的第一反应是该程序应该会报错,因为按照实例内容,b[a]这种表述方式看上去是在实在离谱,然而当我手动测试了一遍后,也大吃一惊。

    没有报错,甚至连一个warning也没有,程序正常运行:

    IT业界:神奇的C语言:一段令人百思不得其解的代码_IT业界_编程语言_rust_课课家
     

    于是我怀疑是不是因为编译器的原因,又在VS 2017上尝试了一遍,结果依旧正常。

    不甘心的我觉得可能是系统内核有关,便再次从虚拟机上的ubantu上gcc编译,果不其然,还是可以运行的通。

     

    我估计不少朋友此刻的内心都是和我一样:开什么玩笑!这语法正确?这程序居然没有报错?这程序居然能正常运行?

    两者不仅结果一样,连物理地址也是相同的。

    在凌乱一番后,我开始研究起了这个程序。终于在翻阅了《C陷阱与缺陷中》,找到了一段关于数组指针的描述。书中说在C语言中,数组和下标是可以互相转换的,即对任何两个表达式a和b,只要其中一个是指针表达式而另一个是整数时,则a[b]和*((a)+b))的结果一致。

    看完之后我表示更不明白了,因为从我个人来讲,确实理解不了将b作为数组索引有什么意义,也是头一次听到这种说法。由于书中没有过多提及,我又跑到GNU C library寻找相关资料,果然找到一段官方的解释,原文如下:

    A postfix expression followed by an expression in [ ] (brackets) specifies an element of an array. The expression within the brackets is referred to as a subscript. The first element of an array has the subscript zero.

    By definition, the expression a[b] is equivalent to the expression *((a) + (b)), and, because addition is associative, it is also equivalent to b[a]. Between expressions a and b, one must be a pointer to a type T, and the other must have integral or enumeration type. The result of an array subscript is an lvalue.

    由于我英语也一般,翻译了一下大概是这个意思,前一段是数组的相关定义,不需要解释。关键在于后一段,根据官方表示:根据数组定义,表达式a[b]等价于表达式*((a)+(b)),并且,由于加法是关联的,所以它也等价于b[a]。不过需要满足一个大前提:a式和b式,两者必须满足一个是指向类型T的指针,另一个必须是整形或枚举型。同时还给了一个具体的例子:

    #include

     

     

    int main(void) {

     

      int a[3] = { 10, 20, 30 };

     

      printf("a[0] = %d\\n", a[0]);

     

      printf("a[1] = %d\\n", 1[a]);

     

      printf("a[2] = %d\\n", *(2 + a));

     

      return 0;

     

    }

    输出结果如下:

    a[0] = 10

     

    a[1] = 20

     

    a[2] = 30

    简单来讲,就是a[b]=*(a+b)=*(b+a)=b[a]。但对于为何这么设定,下面并没有具体说明原因。 

    对此我只想表示,C语言真神奇!

    C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。C语言能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言。尽管C语言提供了许多低级处理的功能,但仍然保持着跨平台的特性,以一个标准规格写出的C语言程序可在包括类似嵌入式处理器以及超级计算机等作业平台的许多计算机平台上进行编译。

课课家教育

未登录