C语言声明解读规则

C的语法在你第一次接触时给你的感觉是灵活而松散,似乎随便你怎么写编译器都能给予解释——也就是可以顺利的编译通过,你甚至可以写出 i = 96 +'a';之类的语句来。

但当你深入学习使用C的时候你会发现C的语法也有其诡谲的一面,其中声明就是很讨厌的一项。我记得自己在学习的时候是靠死记硬背一些基本的声明方式来过关的,顺便说说这种方法在很多情况下都是最好的方法之一。

我们首先来看C语言的术语以及一些能组合成一个声明的单独语法成分。其中一个非常重要的成分就是声明器(declarator),它是所有声明的核心。简单来说,声明器就是标识符以及与它组合在一起的任何指针,函数括号、数组下标等。下表是一个归纳分类
----------------------------------------------------------------------------------------------------------------------------------
数量 C语言中的名字 C语言中出现的形式
----------------------------------------------------------------------------------------------------------------------------------
零个或多个 指针 下列形式之一:
*const volatile
*volatile
*
*const
*volatile const
-----------------------------------------------------------------------------------------------------------------------------------
有且只有一个 直接声明器 标识符
或:标识符[下标]
或:标识符(参数)
或:(声明器)
-----------------------------------------------------------------------------------------------------------------------------------
零个或一个 初始化内容 =初始值
-----------------------------------------------------------------------------------------------------------------------------------

一个声明由下表所示的各个部分组成。声明确定了变量的基本类型以及初始值(如果有的话)。
-----------------------------------------------------------------------------------------------------------------------------------
数量 C语言中的名字 C语言中出现的形式
-----------------------------------------------------------------------------------------------------------------------------------
至少一个类型说明符 类型说明符(type-specifier) void char short int long
signed unsigned
float double
结构说明符(struct-specifier)
枚举说明符(enum-specifier)
联合说明符(union-specifier)

存储类型(storage-class) extern static register
auto typedef

类型限定符(type-qualifier) const volatile
-----------------------------------------------------------------------------------------------------------------------------------
有且只有一个 声明器(declarator) 参见上表的定义
-----------------------------------------------------------------------------------------------------------------------------------
零个或多个 更多的声明器 声明器
-----------------------------------------------------------------------------------------------------------------------------------
一个 分号 ;
-----------------------------------------------------------------------------------------------------------------------------------
记住:在合法的声明中存在限制条件。
1) 函数的返回值不能是一个函数,象foo()()这样是非法的
2) 函数的返回值不能是一个数组,象foo()[]这样是非法的
3) 数组里面不能有函数,象foo[]()这样是非法的


优先级规则:
1) 声明从它的名字开始读取,然后按照优先级顺序依次读取
2) 优先级从高到低依次是:
2.1) 声明中被括号括起来的那部分
2.2)后缀操作符:()表示这是一个函数,[ ]表示一个数组
2.3)前缀操作符: *表示“指向......的指针”
3) 如果const和(或)volatile关键字的后面紧跟类型说明符(如int long等),那么它作用于类型说明符。在其它情况下,const和(或)volatile关键字作用于它左边紧邻的指针星号。

<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter" /> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0" /> <v:f eqn="sum @0 1 0" /> <v:f eqn="sum 0 0 @1" /> <v:f eqn="prod @2 1 2" /> <v:f eqn="prod @3 21600 pixelWidth" /> <v:f eqn="prod @3 21600 pixelHeight" /> <v:f eqn="sum @0 0 1" /> <v:f eqn="prod @6 1 2" /> <v:f eqn="prod @7 21600 pixelWidth" /> <v:f eqn="sum @8 21600 0" /> <v:f eqn="prod @7 21600 pixelHeight" /> <v:f eqn="sum @10 21600 0" /> </v:formulas> <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" /> <o:lock v:ext="edit" aspectratio="t" /> </v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:294.75pt; height:279pt'> <v:imagedata src="file:///C:/DOCUME~1/HZ07442/LOCALS~1/Temp/msohtml1/01/clip_image001.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]-->
<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter" /> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0" /> <v:f eqn="sum @0 1 0" /> <v:f eqn="sum 0 0 @1" /> <v:f eqn="prod @2 1 2" /> <v:f eqn="prod @3 21600 pixelWidth" /> <v:f eqn="prod @3 21600 pixelHeight" /> <v:f eqn="sum @0 0 1" /> <v:f eqn="prod @6 1 2" /> <v:f eqn="prod @7 21600 pixelWidth" /> <v:f eqn="sum @8 21600 0" /> <v:f eqn="prod @7 21600 pixelHeight" /> <v:f eqn="sum @10 21600 0" /> </v:formulas> <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" /> <o:lock v:ext="edit" aspectratio="t" /> </v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:294.75pt; height:279pt'> <v:imagedata src="file:///C:/DOCUME~1/HZ07442/LOCALS~1/Temp/msohtml1/02/clip_image001.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->例:
分析 char * const *(*next)();
这个东西表示“next是一个指针,它指向一个函数,这个函数的返回一个char类型的常量指针”。














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值