为什么在不使用 static_cast 的情况下,const void* 的类型转换在 C 而不是 C++ 中是合法的

Why type casting of const void* is legal in C not C++ without using static_cast

Whosebug 上有几个名称相似的问题,例如 and this one .etc

然而,none 回答了我心中的问题...

问题背景:

我在 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
}

问题:

  1. const pkg_req_t *pkg = packagevoid; --- 为什么这在 C 中是合法的,但在 C++ 中却给出错误?
  2. 在这种情况下 static_cast 是一个优雅的解决方案吗? --- 我问这个问题是因为 const_cast<pkg_req_t*>reinterpret_cast<const pkg_req_t*> 似乎也有效。哪一个更好?
  3. 在编译错误信息中,为什么编译器在错误信息的最后报“[-fpermissive]”?

why this is legal in C but giving error in C++?

在 C++ 中,不允许从 void*T* 的隐式转换,因为它不是 "safe" 转换。取消引用 T* 会导致未定义的行为,除非 void* 实际上确实指向 T 对象。

在创建 C++ 时,在 C 中禁止这种类型的隐式转换为时已晚,因为它会破坏执行此操作的所有代码:

T* p = malloc(sizeof(T));  // malloc returns void*

因此,它在 C 中继续被允许。

Is static_cast an elegant solution in this case?

是的,这就是 "best practices" 执行从 const void*const T* 的转换的方法。

static_castconst_castreinterpret_cast 危险性小,因此应该优先于它们。 dynamic_caststatic_cast 危险性小,但不能在这种情况下使用。

In the compilation error message, why is the compiler reporting "[-fpermissive]" in the end of the error message?

编译器告诉您,如果您使用 -fpermissive 标志编译代码,它将接受从 const void*const T* 的隐式转换,即使标准不允许它。