在比较中使用已强制转换为另一种类型的函数指针是否定义良好?

Is it well defined to use a function pointer that's been cast to another type in a comparison?

本文关键字:指针 函数 类型 是否 定义 另一种 比较 转换      更新时间:2023-10-16

无法直接比较不同类型的功能指针:

#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(*)()的容器,以搜索调用函数的地址,以了解该调用。

来自[expr.reinterpret.cast]

可以将功能指针明确转换为其他类型的功能指针。[...]除了将类型"指针到T1"类型转换为" T2指针"类型(其中T1T2是函数类型)的类型,然后返回其原始类型会产生原始指针值,这是此类的结果。指针转换未指定。

未指定是否施放的功能指针均等。

可以将指针明确转换为任何足够大的积分类型以容纳它。映射功能是实现定义的。

因此,如果实现不使用一些古怪的转换,则自然选择转换为std::intptr_t或其他合适的类型。

来自GCC的文档

如果指针表示大于整数类型,则从指针到整数丢弃最重要的位,如果指针表示小于整数类型,则sign-extends 1 不变。

又名理智转换。在我敢打赌的大多数情况下,这可能是您会发现的。

[1] GCC的未来版本可能零扩展,或使用目标定义的PTR_EXTEND模式。请勿依靠符号扩展。