Skip to main content
 首页 » 编程设计

c++之为什么不使用 static_cast 的 const void* 类型转换在 C 而不是 C++ 中是合法的

2024年12月31日14EasonJim

StackOverflow 上有几个名称相似的问题,例如 this onethis 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 
} 

问题:

  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* 的隐式转换是不允许的,因为它不是“安全”转换。取消引用 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_castconst_castreinterpret_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 的隐式转换* 即使标准不允许。