不能直接比较不同类型的函数指针:
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
// Doesn't compile, the comparison is not allowed
std::cout << std::boolalpha << (&foo == &bar) << std::endl;
return 0;
}
但是,如果将一个函数指针强制转换为另一个函数指针的类型,是否定义了将该投射的结果与其他函数指针进行比较的行为?
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
auto cast_ptr = reinterpret_cast<decltype(&bar)>(&foo);
// Printed "false" when I tried it, but is this guaranteed?
std::cout << std::boolalpha << (cast_ptr == &bar) << std::endl;
}
如果两个运算符都被强制转换为常见但不同的类型怎么样?
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
using cast_type = void(*)();
auto cast_foo = reinterpret_cast<cast_type>(&foo);
auto cast_bar = reinterpret_cast<cast_type>(&bar);
// Also printed "false" when I tried it, but is this guaranteed?
std::cout << std::boolalpha << (cast_foo == cast_bar) << std::endl;
}
我理解函数指针比较相等,当且仅当它们都指向nullptr
或同一函数时。对我来说不清楚的是,是否允许使用在比较中被转换为另一个函数指针类型的函数指针。
上下文
我正在维护一个带有c兼容API的c ++库。该库记录对API函数的每次调用。在运行时有选择地禁用某些功能的日志记录会很有用。就可用性而言,当前最好的提议是提供一个新的API函数,该函数将API函数的指针作为参数,该函数的日志记录应该被抑制。由于API函数具有不同的参数,因此这些指针将具有不同的类型,并且需要转换为常见的函数指针类型,例如void(*)()
。然后,在记录API函数调用之前,将搜索void(*)()
的容器以查找被调用函数的地址,以便知道是否记录该调用。
答案 0 :(得分:0)
函数指针可以显式转换为不同类型的函数指针。 [...]除了将“指向
System.out.println("\f");
的指针”的prvalue转换为“指向T1
的指针”(其中T2
和T1
是函数类型)并且返回其原始类型会产生原始指针值,这种指针转换的结果是未指定的。
未指定铸造函数指针是否相等。
指针可以显式转换为足以容纳它的任何整数类型。映射函数是实现定义的。
因此,转换为T2
或其他合适的类型是自然的选择,前提是实现不会使用某种古怪的转换。
如果指针表示大于整数类型,从指针到整数的转换会丢弃最高有效位,如果指针表示小于整数类型,则签名扩展 1 ,否则位没有变化。
AKA理智的转换。这可能是我在大多数情况下会发现的,我敢打赌。
[1] GCC的未来版本可以零扩展,或使用目标定义的ptr_extend模式。不要依赖签名扩展。