解释复杂声明
下面这个声明符是什么意思呢?
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
3pf
的类型:
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 ***/
在上述情形中,我们可以用指针来获得所需的效果。函数不能返回数组,但可以返回指向数组的指针;函数不能返回函数,但可以返回指向函数的指针;函数型的数组不合法,但是数组可以包含指向函数的指针。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了