解释复杂声明

下面这个声明符是什么意思呢?

int *(*x[10]) (void);

这个声明符组合了*[](),所以x是指针、数组还是函数并不明显。

幸运的是,无论多么费解,有下面两条简单的规则可以用来理解任何声明。

始终从内往外读声明符。换句话说,定位声明的标识符,并且从此处开始解释声明。
在作选择时,始终使[]()优先于*。如果*在标识符的前面,而标识符后面跟着[],那么标识符表示数组而不是指针。同样地,如果*在标识符的前面,而标识符后面跟着(),那么标识符表示函数而不是指针。(当然,可以使用圆括号来使[]()相对于*的优先级无效。)

首先把这些规则应用于简单的示例。在声明

int *ap[10];

 

中,ap是标识符。由于*ap的前面,且后边跟着[],而[]优先级高,所以ap是指针数组。在下列声明中,

float *fp(float);

 

fp是标识符。由于*在标识符的前面,且后边跟着(),而()优先级高,所以fp是返回指针的函数。
下列声明是一个小陷阱:

void (*pf)(int);

由于*pf包含在圆括号内,所以pf一定是指针。但是(*pf)后边跟着(int),所以pf必须指向函数,且此函数带有int型的实际参数。单词void表明了此函数的返回类型。

正如最后那个例子所示,理解复杂的声明符经常需要从标识符的一边折返到另一边;

void    (*pf)    (int)
          1    
                  2
    3
pf的类型:
1. 指针指向;
2. 具有int型实际参数的函数
3. 返回void型值

下面用这种折返方法来解释早前给出的声明:

int *(*x[10])(void);

 

首先,定位声明的标识符(x)。在x前有*,而后边又跟着[]。因为[]优先级高于*,所以取右侧(x是数组)。接下来,从左侧找到数组中元素的类型(指针)。再接下来,到右侧找到指针所指向的数据类型(不带实际参数的函数)。最后,回到左侧看每个函数返回的内容(指向int型的指针)。

要想熟练掌握C语言的声明需要花些时间并且要多练习。唯一的好消息是在C语言中有不能声明的特定内容。函数不能返回数组:

int f(int)[];    /*** wrong  ***/

 

函数不能返回函数:

int g(int)(int);    /*** wrong ***/

 

函数型的数组也是不可能的:

int a[10](int);        /*** wrong ***/

在上述情形中,我们可以用指针来获得所需的效果。函数不能返回数组,但可以返回指向数组的指针;函数不能返回函数,但可以返回指向函数的指针;函数型的数组不合法,但是数组可以包含指向函数的指针。

posted @   木凌云  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示