vlambda博客
学习文章列表

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

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

#include <stdio.h>

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也没有,程序正常运行:

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


于是我怀疑是不是因为编译器的原因,又在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 <stdio.h>

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语言真神奇!






来源:

https://www.toutiao.com/a6824703081989538312/

“IT大咖说”欢迎广大技术人员投稿,投稿邮箱:[email protected]



来都来了,走啥走,留个言呗~




 IT大咖说  |  关于版权 

感谢您对IT大咖说的热心支持!



相关推荐


推荐文章