理解C语言声明的优先级规则

C语言的声明有时会很长,让人感到恐惧。这里描述了一种方法,用通俗的语言把声明分解开来,分别解释各个组成部分。

理解C语言声明的优先级规则的步骤

  1. 声明从它的名字开始读起,然后按照优先级顺序依次读取。

  2. 优先级从高到低依次是:

  • 声明中被括号括起来的那部分

  • 后缀操作符: 括号()表示这是一个函数, 方括号[]表示这是一个数组

  • 前缀操作符:星号*表示“指向...的指针”

  1. 如果const和(或)volatile关键字的后面紧跟类型说明符(如int,long等),那么它作用于类型说明符。在其他的情况下,const和(或)volatile关键字作用于它左边紧邻的指针星号。

例子1: char *const *(*next)();

适用规则解释说明
1从变量名开始,next是...
2.1在把(*next)作为一个整体,得出next是指向...的指针
2.2读后缀(),得出是个函数,这个函数不带参数,所以next是指向函数的指针
2.3(*next)前面的*,得出这个函数返回值是个指针
3char *const部分,const修饰的是指针,这是个指向char类型的常指针

连接在一起就是,next是一个指针,它指向一个函数,这个函数不带参数,它返回另外一个指针,这个指针指向char类型的常量指针。

例子2:char *(* c[10])(int **p)

适用规则解释说明
1从变量c开始
2.1(* c[10])作为一个整体
2.2在这个整体里,读到[],所以c是一个包含10个元素的数组
2.3数组的每个元素是个指针
2.2(int **p)的部分,这是个函数,参数是指向int的指针的指针
2.3这个函数返回的是个指向char类型的指针

所以连接在一起就是,c是一个包含10个元素的数组,数组中的每个元素是个指向函数指针,该函数的声明是这样的,参数是指向int的指针的指针,返回值是指向char类型的指针。

例子3:void (*signal(int sig, void (*func)(int)))(int);

适用规则解释说明
1先读void (*signal(...))(int),针对这部分,先从signal开始
2.1(*signal(...))当作一个整体
2.2signal是个函数
2.3读signal前面的*,得出signal这个函数返回一个指针,该指针是指向函数的指针,函数原型是void f(int)
在读(int sig, void (*func)(int))部分,这部分是signal的参数

所以连接在一起就是,signal是个函数,该函数带2个参数,int和一个函数的指针,该指针所指向的函数原型是void f(int)。signal这个函数的返回为函数的指针,该指针所指向的函数原型也是void f(int)。

虽然这样简洁,但是可读性太差。我们可以借助typedef来实现与上面声明等价的声明。

typedef void (*ptr_to_func) (int);
ptr_to_func signal(int, ptr_to_func);
复制代码

ptr_to_func是一个函数指针,该函数接受int参数,返回值为void。signal是个函数,接受int和一个函数指针作为参数,返回值为ptr_to_func函数指针。

例子4: char (*(*x())[])()

适用规则解释说明
1先把(*x())当成一个整体
2.2x是个函数
2.3该函数返回一个指针
把已经处理的部分拿掉,换个新名称xx,得到char (*xx[])()
2.2xx是个数组
2.3数组的每个元素是个指针,该指针指向函数,函数的原型是 char f()

所以连接在一起就是, x是个函数,函数返回一个指针,指针指向数组,数组的每个元素是个函数的指针,函数的原型是char f()。

《The C Programming Language》第5.12章有写一个dcl工具,它将C语言的声明转换为文字描述。源码我已经整理到我的github,在linux上执行下面的命令即可测试:

git clone git@github.com:rexnie/usefulC.git
cd src/tcpl/ch5/5-18
make
复制代码

即可在当前目录下生成a.out, 执行该文件,得到:

./a.out
char (*(*x())[])()
x:  function returning pointer to array[] of pointer to function returning char
复制代码

参考:

  1. 《The C Programming Language中文版(第2版.新版)》
  2. 《C专家编程》
  3. dcl工具

转载于:https://juejin.im/post/5af061a86fb9a07ace58cd88

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值