C/C++复杂声明包你看懂

关于C/C++的复杂声明

c语言有它独特而复杂的声明规则,在c语言中一个声明是由标识符和关键字组成的一个表达式,注意,这里说的是关键字和标识符一起组成的一个表达式,关键字与标识符的顺序可以以符合语法的方式随意组合。因为大多数简单的声明都是由左边类型右边标识符(变量名)组成,所以给我们造成一种声明语法必须先说明类型再说明变量名的错觉。实际上c语言的声明方式有他自己的一套规则,并不是说简单的从左向右解析,编译器解析声明语句的时候也是按照这一套规则和步骤进行的。

步骤0:有括号的(这里指把变量名括起来的括号而不是函数符号)一律先处理解析括号内的语句,并最后把它当做一个整体进行下一步的解析

步骤1:找到变量名

步骤2:进一步获取类型(具体啥意思见下文),如果右方有[ ]或( )这样的符号则先向右解析,否则向左解析(意思是先向右看再向左看)

  • 向右解析:1,如果是[ ]那么得到它是数组类型,方括号里的数则是数组的大小,若要想知道数组元素的类型便要跳到步骤2,进一步获取类型(这里是数组元素的类型);2,如果是( ),那么得到它是函数,圆括号里便是他的参数列表,若要想知道返回类型也是跳到步骤2,进一步获取类型(这里是函数的返回值的类型)。
  • 向左解析:1,如果出现 * 符号,那么得到它是指针类型,如要想要知道它指向变量的类型,那么要跳到步骤2来进一步获取类型(这里是指针指向的变量的类型);2,如果是const,除非const在整个声明表达式的最左边,那么这个const永远只修饰离它左边离它最近的关键字的类型;3, 如果出现类型符号(如int, char, float等),则得到具体类型,没有进一步需要得到的类型了,所以也意味着解析完成。

小提示:把变量名包括进去的才是括号,要先解析括号里面的东西,而外面的括号则是一个函数标识,表示它是一个函数
以上步骤处理的是一个单纯的变量声明,如果要用typedef声明一个类型,那么上诉步骤中本来是变量名的就会被当成类型名。

总结和例子:注意:上面的步骤处理的不仅仅是指针类型,无论是一般的变量声明还是函数或者是复杂的指针声明都是用上述的步骤去解析的
其实这里像是剥洋葱,也有一点递归得思想在里面,就是一步一步的通过优先级来获取所想知道的类型(这里的优先级是指:优先级括号---->右边([ ]或())---->左边(int,float,*等等)),每次解析一个声明表达式的时候都可以一边解析一边问自己想要知道的类型是什么,然后通过步骤2来获得答案。

例子如下(上述看懂了的可以不用看,可以自己试试)

void(*(*var[10])(int))();
typedef void(*(*var[10])(int))();

注意它们的区别!!!
第一条语句是一个合法的声明语句,它声明且定义了一个变量,这个变量的名字就是var,这个变量的类型就是通过上述步骤得到的类型。
第二条语句是一个typedef的类型声明,它只声明了相应的类型,并没有声明和定义变量,就如同把一般的变量声明语句中的变量名看做类型名。

这里先讲解一下第一个语句,也就是变量名的常规声明。
我们首先找到变量名,这里是var,问自己:它的类型是什么呢?先向右看(步骤2),因为右边有[ ],所以答:他是数组类型;然后接着问自己:数组的元素的类型是什么呢,因为有括号要先解析括号里的(步骤0),所以向左看(步骤2),看到星号,答:数组的元素类型是指针类型;接着问:那么这个指针类型指向的是什么类型呢?优先向右看(步骤2),因为右边出现( )函数符号,所以答:这个指针指向的类型是一个函数,很明显接受一个int参数;又问:这个函数的返回类型是什么呢?因为出现了括号(步骤0),要先解析括号里的,所以向左看看到星号,答:返回类型是一个指针;又问:这个指针指向什么类型呢?向右看(步骤2),右边出现了( )符号所以这个指针指向一个函数;问:这个函数的返回值是什么呢?向右看(步骤2),没有[ ]或(),所以只能向左看进而看到void标识,所以答:无返回值;
所以最后的答案是:它是一个数组元素为指针的数组,指针指向一个函数,这个函数接受一个int作为参数并且返回一个指针,这个指针又指向一个函数,这个函数无参数无返回值。
参考书目:《c专家编程》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值