6

在 C 中,将指针转换为void *.

移植到 C++ 的一个主要障碍是在从处理泛型指针(malloc例如void *block_get(Blkno const blkno);.

但是,我的代码旨在由 CC++ 编译器成功编译。如果我为了 C++ 而在任何地方都提供了显式转换,那么它们必须是 C 风格的转换,并且由于在两种语言的指针类型之间转换非指针类型,我可能会掩盖错误。

我的参考错误如下:

struct Cpfs *cpfs = calloc(1, sizeof(*cpfs));

在 MSVC 中产生:

错误 2 错误 C2440: 'initializing' : 无法从 'void *' 转换为 'Cpfs *' e:\src\cpfs\cpfs.c 179

显然我不能使用new,或者static_cast如果我不再使用 C,我自然会使用它。为每种语言提供最大类型安全性的最佳方法是什么?void *

4

5 回答 5

5

我建议要么简单地使用 C 样式转换,要么将转换包装在一个宏中,该宏要么扩展为空(在 C 中),要么static_cast在 C++ 中。

于 2010-10-03T09:39:54.113 回答
2

如果您的编译器支持decltype(),您可以使用一些宏魔术来避免必须显式重复类型名称(并且,由于sizeof,元素大小):

#ifdef __cplusplus
#define my_calloc(VAR, COUNT) \
    static_cast<decltype(VAR)>(std::calloc(COUNT, sizeof *VAR))
#else
#define my_calloc(VAR, COUNT) calloc(COUNT, sizeof *VAR)
#endif

示例用法:

#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif

struct Cpfs *cpfs = my_calloc(cpfs, 42);

更清洁的解决方案可能是只使用 C 编译器并链接目标文件,不过......

于 2010-10-03T10:47:41.343 回答
1

制作一个替换分配器函数,您可以为 C 和 C++ 构建以不同方式定义:- 在头文件中类似这样的内容:

#ifdef __cplusplus
template<typename TypeT>
TypeT* MyAlloc(TypeT** pOut,size_t cb){
  *pOut = static_cast<TypeT*>(malloc(cb)); //aint c++ pretty.
  return *pOut;
}
#else
  extern void* MyAlloc(void** ppv, size_t cb);
#endif

现在,在 c++ 构建中,您有一个可以推断其处理的事物类型的函数,而在 C 构建中,它是一个返回 void* 的常规函数​​。

唯一的问题是需要传递指针以进行分配 - c++ 编译器不会尝试仅根据函数 afaik 的返回类型推断模板参数。所以你可以这样称呼它:-

int *p;
if(MyAlloc(&p,sizeof(int)*n)){
  ...
于 2010-10-03T09:53:41.360 回答
0

我知道的唯一解决方案是进行显式转换:

struct Cpfs *cpfs = (Cpfs*)calloc(1, sizeof(*cpfs));

这里两个编译器都满意。还请记住,对于较旧的编译器,malloc 可能会返回 char*。

hth

马里奥

于 2010-10-03T09:43:07.933 回答
0

也许是这样的?(未经测试,没有可用的编译器,不经常使用宏):

#ifdef __cplusplus
    #define pointer_cast(type, pointer) reinterpret_cast<type>(pointer)
#else
    #define pointer_cast(type, pointer) (type)(pointer)
#endif
于 2010-10-03T09:53:29.453 回答