C语言声明的优先级规则

2015/07/15 技术

C语言声明的优先级规则

今天看《C专家编程》,其中由有一张讲声明,其中讲声明的优先级很有用,现在记录一下,以备后期查看.

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

实例

1. char * const *(*next)()

我们来分析上面的这个声明

  1. 根据上面的规则1, 确定名字是next.其中括号括起来的部分是(*next)
  2. 根据2.3确认next是指向…的指针.
  3. 分析完了(*next),然后我们将(*next)作为一个整体. 再根据2.2的原则,(*next)后边是一个括号,便是一个函数,说明next现在是: 指向函数的指针, 指向一个返回…的函数,此时(*next)()是一个整体.
  4. 再根据2.3, 处理前缀(next)()的前缀"",说明这个函数返回一个指针,这个指针指向…类型.将*(*next)()作为一个整体.
  5. 根据3的原则,const修饰的时他左边紧邻的指针星号.char * const说明是一个指向char类型的常量指针.

所以最后总结起来就是: next是一个指针,它指向一个指针,该函数返回另一个指针,这个指针指向一个类型为char的常量指针.

2. void ( *signal(int sig, void(*func)(int) ))( int )

我们来分析上面的这个声明:

  1. 我们根据上面的规则进行分析,首先先找到声明,我们从左到右查找最内层的声明,找到如下声明:

    void(*func)(int)
    

    说明func是一个指向函数的指针.该函数的形参为int,返回值为void,

  2. 我们接下来注意到了前面的int sig我们发现他和void(*func)(int)是平级的,这说明func不是我们要说明的东西,因为我们不可能声明两个.
  3. 再往前分析,为我们注意到剩下的部分

    void ( *signal(       )) ( int )
    

    根据上面的经验,signal才是我们的要声明的的东西.

  4. 根据规则2,我们发现signal是一个函数(因为signal后边跟的时括号,而且后缀的优先级比前缀高),这就确定了signal得属性,它是一个函数.
  5. 我们再来看signal这个函数的特殊性. 现在剩下的部分是

    void (* ..... )(int)
    

    我们分析剩下的部分.由规则2.1,我们分析(* …)是一个指针,后边跟着(int),所以是一个函数指针,这个函数的形参是int,返回值时void

  6. 现在我们基本分析完了,把我们分析出来的总结一下:

    signal 是一个函数,他返回一个函数指针,返回的这个函数指针的形参是int,返回值是void. signal这个函数的形参有两个,第一个就是int,
    第二个形参是一个函数指针,这个函数指针func的形参是int,返回值是void.我们可以发现signal这个函数的第二个形参,和它本身的返回值类型相同的
    

使用typedef来理解signal定义.

signal这个函数的定义,基本上是c语言中最复杂的声明类型,我们可以通过typedef来帮助我们理解signal的定义. 首先定义如下:

typedef void(*ptr_to_func)(int);

我们定义ptrtofunc为一个指针,他指向一个函数,这个函数的形参是int,返回值为void 我们再来看signal的定义

void ( *signal(int sig, void(*func)(int) ))( int )

根据我们上面的分析的分析我们可以做如下的简化

ptr_to_func signal(int sig, ptr_to_func func);

这样看起来是不是清爽很多!

Search

    Table of Contents