函数指针地址在转换后是否保留?

6
据我所知,C++标准允许将函数指针转换为不同的类型(只要不调用它们):
int my_func(int v) { return v; }

int main() {
    using from_type = int(int);
    using to_type = void(void);

    from_type *from = &my_func;
    to_type *to = reinterpret_cast<to_type *>(from);

    // ...
}

此外,如果我将指针转换回其原始类型并调用它,则不会出现未定义的行为。

到目前为止,一切都很好。那么接下来呢?

const bool eq = (to == reinterpret_cast<to_type *>(my_func));

在转换后地址是否也仍然有效并非标准所保证。


虽然这与问题无关,但可能情况是当采用类型擦除技术时。如果地址仍然有效,则可以在不知道原始函数类型的情况下完成某些操作。


实际上,我不是在询问比较普通函数指针的问题,而是在问函数指针转换后地址是否保持不变。"比较"这个词只是为了更清楚地表达我的意思。 - skypjack
此外,我的问题的答案很可能是“不”,但请勿透露。这使得 dup 调用更加不太可能。 :) - skypjack
1个回答

5

[expr.reinterpret.cast].6 (我强调的部分):

函数指针可以显式地转换为不同类型的函数指针。 [...]

除了将类型为“指向T1的指针”的prvalue转换为类型 “指向T2的指针”(其中T1和T2是函数类型),然后再回到其 原始类型会产生原始指针值之外,这种指针转换的结果是未指定的。

因此,标准明确允许将函数指针强制转换为不同FP类型,然后返回。这是reinterpret_cast函数指针的一种例外,它通常是不确定的。

在我的理解中,这意味着to == reinterpret_cast<to_type *>(my_func)并不一定为true


由于 is unspecified 标记。尽管这非常不幸,但这是有道理的。 :( - skypjack
1
@skypjack 标准可能故意给编译器留下了很大的余地,但我无法想象任何合理的实现策略在其中不会保持一致。我认为它没有任何实际意义。reinterpret_cast 也不能用于常量表达式,因此对于这些表达式的有效性也不是一个问题。 - user17732522
1
我同意这很难看到可能的用途,但是在我的生产代码中,我不想依赖于“它是一个安全UB”的策略。你知道的。 :) - skypjack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接