在C语言中,将指针投向和投自于 void *
.
移植到C++中的一个主要障碍是,当从处理通用指针的函数返回时,需要投掷指针,例如 malloc
以及在我自己的代码中声明的函数,如 void *block_get(Blkno const blkno);
.
然而,我的代码是打算用C语言编译的。和 C++编译器成功。如果我为了C++的缘故,到处提供了显式的casts,那么它们一定是C式的casts,我可能会由于将非指针类型投向和从两种语言的指针类型投出而掩盖了bug。
我的引用错误如下。
struct Cpfs *cpfs = calloc(1, sizeof(*cpfs));
在MSVC中会产生:
错误2 错误C2440:"初始化":不能从 "void *"转换为 "Cpfs *" e:\src\cpfs\cpfs.c 179
显然,我不能使用 new
或 static_cast
如果我不再使用C语言,我自然会使用它。什么是提供最大的类型安全的最佳方式,围绕在 void *
为每一种语言提供最小的啰嗦?
也许是这样的?(未经测试,没有编译器,不经常使用宏)。
#ifdef __cplusplus
#define pointer_cast(type, pointer) reinterpret_cast<type>(pointer)
#else
#define pointer_cast(type, pointer) (type)(pointer)
#endif
我建议要么简单地使用C语言风格的casts, 要么用一个宏把cast包装起来,要么什么也不做(在C语言中),要么用一个宏把cast包装起来 static_cast
在C++中,如果你的编译器支持
如果你的编译器支持 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编译器并链接对象文件,尽管... ...
做一个替换分配器函数,你可以为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++编译器不会只根据函数的返回类型来推断模板参数。所以,你可以像这样调用它的agnostically:-
int *p;
if(MyAlloc(&p,sizeof(int)*n)){
...
我知道的唯一的解决方案是做显式转换。
struct Cpfs *cpfs = (Cpfs*)calloc(1, sizeof(*cpfs));
这里,两个编译器都能满足要求。另外,请记住,对于旧的编译器,malloc可能返回char*。
hth
马里奥