解释复杂声明
下面这个声明符是什么意思呢?
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 ***/
在上述情形中,我们可以用指针来获得所需的效果。函数不能返回数组,但可以返回指向数组的指针;函数不能返回函数,但可以返回指向函数的指针;函数型的数组不合法,但是数组可以包含指向函数的指针。

浙公网安备 33010602011771号