C++中函数指针转换后地址是否保持一致?
C++函数指针跨类型转换后的地址相等性是否受标准保证?
问题背景
已知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));
这种地址相等性是否为C++标准所保证?(注:该问题的应用场景为类型擦除,若地址保持一致,则无需知晓原函数类型即可进行相关操作。)
解答
标准层面的规定
C++标准并未保证不同类型的函数指针转换后地址值相等。标准仅明确:如果将一个函数指针转换为另一个函数指针类型,再转换回原类型,得到的指针与原指针完全相等。但对于"直接转换原函数到目标类型"和"通过原函数指针转换到目标类型"的结果是否相等,没有强制要求。实际编译器的常见行为
在GCC、Clang、MSVC等主流编译器的实现中,函数指针通常直接指向函数的入口地址,因此无论转换为哪种函数指针类型,地址值都会保持一致。但这属于编译器的具体实现逻辑,而非标准强制要求,依赖此行为编写的代码不具备完全可移植性。类型擦除场景的可靠方案
如果需要在类型擦除场景下安全判断函数标识,更稳妥的方式包括:
- 将函数指针转换为
void*(注意:标准仅保证转换回原函数指针类型有效,不同函数指针转void*后的相等性同样无标准保证,但多数实现支持); - 为每个函数关联唯一标识(如静态全局变量的地址、预计算的哈希值等),通过标识完成比较,而非直接依赖转换后的函数指针地址。
内容的提问来源于stack exchange,提问作者skypjack
相关产品推荐
相关产品推荐

