c++ - c和c++中函数指针转换的区别
问题描述
我的代码在 c 和 c++ 中的行为不同。
void *(*funcPtr)() = dlsym(some symbol..) ; // (1) works in c but not c++
int (*funcPtr)();
*(void**)(&funcPtr) = dlsym(some symbol..) ; // (2) works in c++
我不明白第二次铸造如何在 c++ 中工作,而第一次铸造在 c++ 中不起作用。(1) show 的错误消息是 c++ 中从 void* 到 void*() 的无效转换。
解决方案
问题是dlsym
返回一个void*
指针。虽然在 C 中,任何此类指针都可以隐式转换为任何其他(对象!)指针类型(为了比较:强制转换 malloc 的结果),但在 C++ 中并非如此(这里您需要强制转换 malloc的结果)。
但是,对于函数指针,即使在 C 中,这种强制转换也不是隐式的。显然,当您的代码编译时,您的编译器也为函数指针添加了这种隐式强制转换,作为编译器扩展(与对象指针一致);然而,为了完全符合标准,它实际上应该发出诊断信息,例如 C17 6.5.4.3 规定的编译器警告:
涉及指针的转换,除了 6.5.16.1 的约束允许的情况外,应通过显式转换来指定。
但现在,与其转换目标指针,不如将结果dlsym
转换为适当的函数指针:
int (*funcPtr)() = reinterpret_cast<int(*)()>(dlsym(some symbol..));
或更简单:
auto funcPtr = reinterpret_cast<int(*)()>(dlsym(some symbol..));
甚至:
int (*funcPtr)() = reinterpret_cast<decltype(funcPtr)>(dlsym(some symbol..));
funcPtr
(如果之前已经声明过,最后一个特别有趣。)
此外,您应该更喜欢 C++ 而不是 C 样式转换,请参阅上面的我的变体。您可以更精确地控制实际发生的类型转换。
旁注:您是否注意到问题中声明的两个函数指针的返回类型(void*
vs. int
)不同?此外,在 C 中不接受任何参数的函数需要声明为void f(void)
; 因此,函数指针:void*(*f)(void)
. C++ 允许使用void
for 兼容性,而void
在 C 中跳过具有完全不同的含义:该函数可以接受任何东西,您需要从其他地方(文档)知道实际上可以传递多少个类型的参数。
推荐阅读
- firebase - Google Cloud Firestore 安全规则 - 文档 ID 规则
- android - 当我在颤动中将语言设置为“马来西亚”时显示错误
- jxbrowser - 如果另一个浏览器使用 window.open 打开浏览器,则浏览器中的 executeJavaScriptAndReturnValue 返回的 JsValue 的 jsContext 为空
- mongodb - 是否可以以索引支持的方式在同一个数组上执行“$unwind”和“$sort”?
- c# - 在内存数据库提供程序中使用 EF core 对 asp.net core 应用程序进行单元测试的优势
- arrays - 将数据从阵列拉入开关阵列
- angular - 更新全局 style.css 文件后如何更新 Angular 4 中的 DOM?
- javascript - 可观察的
> 不可分配给 Observable 类型 httpclient 角度 - ios - 未使用滚动转换样式调用 UIPageViewController 委托方法
- php - PHP 不显示任何 JSON 响应