“螺旋”规则属于以下优先级规则:
T *a[] -- a is an array of pointer to T
T (*a)[] -- a is a pointer to an array of T
T *f() -- f is a function returning a pointer to T
T (*f)() -- f is a pointer to a function returning T
下标[]
和函数调用()
运算符比一元更高的优先级*
,所以*f()
被解析为*(f())
与*a[]
被解析为*(a[])
。
所以,如果你想有一个指针数组或指针的函数,那么你需要明确组*
与标识符,如(*a)[]
或(*f)()
。
然后您意识到了,a
并且f
可能不仅仅是标识符,而且是更复杂的表达式。在T (*a)[N]
,a
可以是一个简单的标识符,或者它可以是一个函数调用等(*f())[N]
(a
- > f()
),或者它可以像一个数组(*p[M])[N]
,(a
- > p[M]
),或者它可以是一个指针数组,以功能,如(*(*p[M])())[N]
(a
- > (*p[M])()
),等等
如果间接操作符*
是后缀而不是一元,那将是很好的选择,这将使声明从左到右更容易阅读(void f[]*()*();
肯定比的流更好void (*(*f[])())()
),但事实并非如此。
当遇到类似这样的毛骨悚然的声明时,请先找到最左边的标识符并应用上面的优先级规则,然后将它们递归地应用于任何函数参数:
f -- f
f[] -- is an array
*f[] -- of pointers ([] has higher precedence than *)
(*f[])() -- to functions
*(*f[])() -- returning pointers
(*(*f[])())() -- to functions
void (*(*f[])())(); -- returning void
signal
标准库中的功能可能是这种精神错乱的类型标本:
signal -- signal
signal( ) -- is a function with parameters
signal( sig, ) -- sig
signal(int sig, ) -- which is an int and
signal(int sig, func ) -- func
signal(int sig, *func ) -- which is a pointer
signal(int sig, (*func)(int)) -- to a function taking an int
signal(int sig, void (*func)(int)) -- returning void
*signal(int sig, void (*func)(int)) -- returning a pointer
(*signal(int sig, void (*func)(int)))(int) -- to a function taking an int
void (*signal(int sig, void (*func)(int)))(int); -- and returning void
在这一点上,大多数人都说“使用typedefs”,这当然是一个选择:
typedef void outerfunc(void);
typedef outerfunc *innerfunc(void);
innerfunc *f[N];
但...
您将 如何f
在表达式中使用?您知道它是一个指针数组,但是如何使用它执行正确的功能?您必须仔细检查typedef并找出正确的语法。相比之下,“裸”版本看上去很麻烦,但是它可以告诉您确切如何在表达式中使用 f
(即(*(*f[i])())();
,假设两个函数都不带参数)。