StackOverflow 上有几个名称相似的问题,例如 this one和 this one .etc
然而,他们都没有回答我心中的疑问……
问题背景:
我在 C++ 代码中包含了一个 C 头文件。有问题的C代码如下所示:
// C header file
static inline bool post_request(const customer_t *requester, const void *packagevoid)
{
const pkg_req_t *pkg = packagevoid;
...
... // some other code
}
编译器提示:
/<project_path>/handler_util.h:250:26: error: invalid conversion from 'const void*' to 'const const pkg_req_t*' {aka 'const pkg_req_s*'} [-fpermissive]
const pkg_req_t *pkg = packagevoid;
^~~~~~~
我将转换更改为显式使用 static_cast
:
// C header file: fixed
static inline bool post_request(const customer_t *requester, const void *packagevoid)
{
#ifdef __cplusplus
const pkg_req_t *pkg = static_cast<const pkg_req_t*>(packagevoid);
#else
const pkg_req_t *pkg = packagevoid;
#endif
...
... // some other code
}
问题:
-
const pkg_req_t *pkg = packagevoid;
--- 为什么这在 C 中是合法的,但在 C++ 中却给出错误? - 在这种情况下,static_cast 是一个优雅的解决方案吗? --- 我问这个问题是因为看来
const_cast<pkg_req_t*>reinterpret_cast<const pkg_req_t*>
也有效。哪一个更好? - 在编译错误信息中,为什么编译器在错误信息的末尾报告“[-fpermissive]”?
请您参考如下方法:
why this is legal in C but giving error in C++?
在 C++ 中,从 void*
到 T*
的隐式转换是不允许的,因为它不是“安全”转换。取消引用 T*
会导致未定义的行为,除非 void*
实际上确实指向了一个 T
对象。
在创建 C++ 时,在 C 中禁止这种类型的隐式转换为时已晚,因为它会破坏执行此操作的所有代码:
T* p = malloc(sizeof(T)); // malloc returns void*
因此,它在 C 中继续被允许。
Is static_cast an elegant solution in this case?
是的,这是执行从 const void*
到 const T*
的转换的“最佳实践”方式。
static_cast
比 const_cast
和 reinterpret_cast
危险性小,因此应该优先于它们。 dynamic_cast
的危险性低于 static_cast
,但不能在这种情况下使用。
In the compilation error message, why is the compiler reporting "[-fpermissive]" in the end of the error message?
编译器告诉您,如果您使用 -fpermissive
标志编译代码,它将接受从 const void*
到 const T 的隐式转换*
即使标准不允许。