“螺旋”规则实际上是以下优先级规则的自然结果:
T *a[]
T (*a)[]
T *f()
T (*f)()
下标运算符
[]
和函数调用运算符
()
的优先级比一元运算符
*
高,所以
*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 *)
标准库中的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
在这种情况下,大多数人会说“使用typedef”,这当然是一种选择:
typedef void outerfunc(void);
typedef outerfunc *innerfunc(void);
innerfunc *f[N];
但是...
你知道它是一个指针数组,但是如何在表达式中使用 f
呢?您必须查看typedef并仔细推断出正确的语法。相比之下, "naked"版本非常难懂,但它确切地告诉您如何在表达式中使用 f
(即(*(*f[i])())();
,假设两个函数都不带参数)。
f
是一个指向可以取任何参数的函数指针数组,如果它是void (*(*f[])(void))(void)
, 那么就是没有参数的函数了。 - txtechhelp