首页 > 解决方案 > 函数(指针)作为参数

问题描述

为什么这个函数调用在没有“地址”运算符(&)的情况下都有效?
如果有人可以就同一问题举一个更简单的例子,我会理解主要思想。

#include <iostream>
using namespace std;
void sum(int, int);
void fun(int, int, void (*)(int, int));

int main()
{
    fun(3,4, &sum); // Why does this line work with and without the `&`?
    return 0;
}

void sum(int a, int b)
{
    cout << a+b;
}

void fun(int a, int b, void (*ptr)(int, int))
{
    (*ptr)(a,b);
}

标签: cfunctionpointers

解决方案


C 2018 6.3.2.1 3 说:

函数指示符是具有函数类型的表达式。除非它是运算符的操作数sizeof或一元运算符,否则&类型为“函数返回类型”的函数指示符将转换为类型为“指向函数返回类型的指针”的表达式。

C++ 执行相同的自动转换,尽管其规范分布在标准中的多个条款中。

因此, in fun(3,4, &sum);,sum不会转换为指针,因为它是 的操作数&。但随后&获取地址,生成指向函数的指针。或者, infun(3,4, sum);自动sum转换为指向函数的指针,产生相同的结果。

(*ptr)(a,b)中,*和括号是不必要的。函数调用运算符 ,(…)从技术上讲,将指向函数的指针作为其左操作数,因此ptr(a, b)提供该指针。在(*ptr)(a,b)中,*ptr取消引用指针,生成函数指示符。然后这个函数指示符会自动转换回一个指针。因此,表达式等价于(&*ptr)(a, b),即等价于ptr(a, b)

事实上,如果你写(**ptr)(a, b)*ptr变成&*ptr如上,然后*&*ptr再次产生函数指示符,并且再次自动转换,产生&*&*ptr,相当于ptr。您可以添加任意数量的*运算符,它们都将被自动转换撤消;你可以写(**************ptr)(a, b)

还有对应于自动转换的函数参数声明的自动调整。如果一个参数被声明为一个函数,就像在ptrof 中一样void fun(int a, int b, void ptr(int, int)),它会自动调整为一个指向函数的指针,就好像它已经被写入了一样void fun(int a, int b, void (*ptr)(int, int))


推荐阅读