为什么以下工作?
void foo() {
cout << "Foo to you too!\n";
};
int main() {
void (*p1_foo)() = foo;
void (*p2_foo)() = *foo;
void (*p3_foo)() = &foo;
void (*p4_foo)() = *&foo;
void (*p5_foo)() = &*foo;
void (*p6_foo)() = **foo;
void (*p7_foo)() = **********************foo;
(*p1_foo)();
(*p2_foo)();
(*p3_foo)();
(*p4_foo)();
(*p5_foo)();
(*p6_foo)();
(*p7_foo)();
}
原文由 Jimmy 发布,翻译遵循 CC BY-SA 4.0 许可协议
有几个部分允许所有这些运算符组合以相同的方式工作。
所有这些工作的根本原因是函数(如
foo
)可以隐式转换为指向函数的指针。这就是为什么void (*p1_foo)() = foo;
起作用的原因:foo
被隐式转换为指向自身的指针,并且该指针被分配给p1_foo
。一元
&
应用于函数时,会产生指向函数的指针,就像它应用于对象时会产生对象的地址一样。对于指向普通函数的指针,由于隐式的函数到函数指针的转换,它总是多余的。无论如何,这就是void (*p3_foo)() = &foo;
起作用的原因。一元
*
应用于函数指针时,会产生指向函数,就像它应用于指向对象的普通指针时会产生指向对象一样。这些规则可以组合。考虑倒数第二个例子,
**foo
:foo
被隐式转换为指向自身的指针,第一个*
应用于该函数指针,再次产生函数foo
。*
,再次产生函数foo
。您可以添加任意数量的
*
s,结果总是一样的。*
越多越好。我们也可以考虑你的第五个例子,
&*foo
:foo
被隐式转换为指向自身的指针;一元*
被应用,再次产生foo
。&
应用于foo
,生成指向foo
的指针,该指针分配给变量。&
只能应用于函数,不能应用于已转换为函数指针的函数(当然,除非函数指针是变量,在这种情况下结果是指针-to-a-pointer-to-a-function;例如,您可以添加到列表中void (**pp_foo)() = &p7_foo;
)。这就是
&&foo
不起作用的原因:&foo
不是函数;它是一个函数指针,它是一个右值。但是,&*&*&*&*&*&*foo
会起作用,就像&******&foo
一样,因为在这两个表达式中&
总是应用于函数而不是右值函数指针。另请注意,您不需要使用一元
*
通过函数指针进行调用;(*p1_foo)();
和(p1_foo)();
都具有相同的结果,这也是因为函数到函数指针的转换。