为什么函数指针定义可以与任意数量的 & 符号 '&' 或星号 '\*' 一起使用?

新手上路,请多包涵

为什么以下工作?

 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 许可协议

阅读 338
1 个回答

有几个部分允许所有这些运算符组合以相同的方式工作。

所有这些工作的根本原因是函数(如 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)(); 都具有相同的结果,这也是因为函数到函数指针的转换。

原文由 James McNellis 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题