小编典典

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

all

为什么以下工作?

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)();
}

阅读 66

收藏
2022-05-30

共1个答案

小编典典

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

所有这些工作的根本原因是函数(如foo)可以隐式转换为指向函数的指针。这就是为什么void (*p1_foo)() = foo;起作用:
foo被隐式转换为指向自身的指针,并且该指针被分配给p1_foo.

一元&应用于函数时,会产生一个指向函数的指针,就像它应用于对象时会产生对象的地址一样。对于指向普通函数的指针,由于隐式的函数到函数指针的转换,它总是多余的。无论如何,这就是为什么void (*p3_foo)() = &foo;有效。

一元*,当应用于函数指针时,会产生指向函数,就像它应用于指向对象的普通指针时会产生指向对象一样。

这些规则可以组合。考虑你的倒数第二个例子,**foo

  • 首先,foo隐式转换为指向自身的指针,第一个*应用于该函数指针,foo再次产生函数。
  • 然后,结果再次隐式转换为指向自身的指针,并*应用第二个,再次产生函数foo
  • 然后它再次隐式转换为函数指针并分配给变量。

你可以添加任意多*的s,结果总是一样的。s越多*,越快乐。

我们还可以考虑您的第五个示例&*foo

  • 首先,foo被隐式转换为指向自身的指针;一元*被应用,再次让步foo
  • 然后,将&应用于foo,产生指向 的指针foo,该指针被分配给变量。

但是,&它只能应用于函数,不能应用于已转换为函数指针的函数(当然,除非函数指针是变量,在这种情况下结果是指向指针的指针- to-a-
function;例如,您可以添加到您的列表中void (**pp_foo)() = &p7_foo;)。

这就是为什么&&foo不起作用: &foo不是函数;它是一个函数指针,它是一个右值。但是,&*&*&*&*&*&*foo会像
一样工作&******&foo,因为在这两个表达式中,&总是应用于函数而不是右值函数指针。

另请注意,您不需要使用一元*通过函数指针进行调用;两者都(*p1_foo)();具有(p1_foo)();相同的结果,同样是因为函数到函数指针的转换。

2022-05-30