c - 函数(指针)作为参数
问题描述
为什么这个函数调用在有和没有“地址”运算符(&
)的情况下都有效?
如果有人可以就同一问题举一个更简单的例子,我会理解主要思想。
#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);
}
解决方案
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)
。
还有对应于自动转换的函数参数声明的自动调整。如果一个参数被声明为一个函数,就像在ptr
of 中一样void fun(int a, int b, void ptr(int, int))
,它会自动调整为一个指向函数的指针,就好像它已经被写入了一样void fun(int a, int b, void (*ptr)(int, int))
。
推荐阅读
- plsql - 有人可以帮助解决这些plsql问题吗,我很难完全理解它
- c# - 尝试在服务层.Net Core中使用自动映射器时出现红色下划线错误
- swift - Swift 中奇怪的 UI 错误
- hive - 错误:org.apache.thrift.transport.TTransportException java.net.SocketException: Broken pipe (Write failed) (State=08S01,code=0)
- vue.js - 页面加载后创建 VUE 组件
- javascript - 如何样式化谷歌地图信息窗口
- spring-boot - 如何在 JPA 中调整日期时间长度?
- javascript - 如果 api 响应 Angular 中没有数据,则显示 div
- c++ - 具有奇怪行为的 C++ std::vector push_back
- google-chrome - 如何选择内存缓存和磁盘缓存