这样做有几个方面,使所有这些运算符组合可以相同的方式工作。
所有这些工作的根本原因是一个函数(如foo
)可以隐式转换为指向该函数的指针。这就是void (*p1_foo)() = foo;
工作原理: foo
将其隐式转换为指向自身的指针,并将该指针分配给p1_foo
。
一元&
函数在应用于函数时会产生指向函数的指针,就像在将其应用于对象时会产生对象的地址一样。对于指向普通函数的指针,由于隐式的函数到函数指针的转换,它总是多余的。无论如何,这就是为什么void (*p3_foo)() = &foo;
可行。
一元 *
变量在应用于函数指针时会产生指向对象的函数,就像将其应用于指向对象的普通指针时会产生指向对象一样。
这些规则可以合并。考虑您倒数第二个示例**foo
:
- 首先,
foo
将其隐式转换为指向自身的指针,然后将第一个*
应用于该函数指针,foo
再次产生该函数。
- 然后,将结果再次隐式转换为指向自身的指针,并
*
应用第二个指针,再次产生函数foo
。
- 然后将其再次隐式转换为函数指针,并分配给该变量。
您可以根据需要添加任意多个*
,结果始终相同。*
s 越多,越好。
我们也可以考虑您的第五个示例&*foo
:
- 首先,
foo
被隐式转换为指向自身的指针;一元*
应用,foo
再次屈服。
- 然后,将
&
应用于foo
,产生指向的指针foo
,该指针已分配给该变量。
尽管&
只能应用于函数,而不能应用于已转换为函数指针的函数(当然,除非函数指针是变量,在这种情况下,结果是指向指针的指针-功能;例如,您可以将其添加到列表中void (**pp_foo)() = &p7_foo;
)。
这就是为什么&&foo
不起作用的 原因&foo
。它是一个作为右值的函数指针。但是,它&*&*&*&*&*&*foo
也可以工作,&******&foo
因为在这两个表达式中,&
始终将应用于函数而不是将rvalue应用于函数指针。
还要注意,您不需要使用一元*
函数通过函数指针进行调用;双方(*p1_foo)();
并(p1_foo)();
有再次因为函数到函数指针转换的结果相同。
&foo
接受的地址foo
,这导致函数指针指向foo
,正如人们所期望的那样。