在 C++ 中放松 void * 铸造

发布于 2024-09-26 01:32:18 字数 677 浏览 5 评论 0原文

在 C 中,将指针转换为 void * 或从 void * 转换指针并不是错误。

移植到 C++ 的一个主要障碍是,从处理通用指针(例如 malloc)的函数返回时需要强制转换指针,以及在我自己的代码中声明的函数(例如 void *block_get(Blkno const) blkno);。

然而,我的代码旨在由 C 和 C++ 编译器成功编译。如果我为了 C++ 的缘故而在各处提供显式强制转换,那么它们一定是 C 风格的强制转换,并且我可能会掩盖由于将非指针类型与两种语言的指针类型进行强制转换而产生的错误。

我的参考错误如下:

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

在 MSVC 中产生:

错误 2 错误 C2440:“初始化”:无法从“void *”转换为“Cpfs *”e:\src\cpfs\cpfs.c 179

显然我无法使用 newstatic_cast 如果我不再使用 C,我自然会使用它。以最少的冗长为每种语言提供围绕 void * 的最大类型安全性的最佳方法是什么?

In C, it's not an error to cast pointers to and from void *.

A major obstacle in porting to C++ is the need to cast pointers when returning from functions dealing with generic pointers such as malloc, and functions declared in my own code such as void *block_get(Blkno const blkno);.

My code however is intended to be compiled by C and C++ compilers successfully. If I provide explicit casts everywhere for the sake of C++, they must be C-style casts and I may be masking bugs due to casting non-pointer types to and from pointer types from both languages.

My reference error is the following:

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

which in MSVC produces:

Error 2 error C2440: 'initializing' : cannot convert from 'void *' to 'Cpfs *' e:\src\cpfs\cpfs.c 179

Evidently I can't use new or static_cast which I'd naturally use if I was no longer using C. What's the best way to provide maximum type safety surrounding void *for each language with minimal verbosity?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

探春 2024-10-03 01:32:18

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

I'd suggest either simply using C style casts, or wrapping the cast in a macro that either expands to nothing (in C), or a static_cast in C++.

暗地喜欢 2024-10-03 01:32:18

如果您的编译器支持 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 编译器并链接目标文件,不过......

If your compiler supports decltype(), you can use some macro magic to avoid having to explicitly repeat the type name (and, thanks to sizeof, the element size):

#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

Example usage:

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

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

The cleaner solution would probably be to just use a C compiler and link the object files, though...

薄情伤 2024-10-03 01:32:18

创建一个替换分配器函数,您可以为 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++ 编译器不会尝试仅根据函数的返回类型推断模板参数。所以你可以像这样不可知论地称呼它:-

int *p;
if(MyAlloc(&p,sizeof(int)*n)){
  ...

make a replacement allocator function that you can define differently for C and C++ builds :- Something like this in a header file:

#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

Now you have, in c++ builds, a function that can infer the type of thing its dealing with, and in C builds, its a regular function that returns a void*.

The only problem is the need to pass in the pointer to allocate - the c++ compiler wont try to deduce a template parameter based only on the return type of a function afaik. So you could call it agnostically like this :-

int *p;
if(MyAlloc(&p,sizeof(int)*n)){
  ...
笨死的猪 2024-10-03 01:32:18

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

#ifdef __cplusplus
    #define pointer_cast(type, pointer) reinterpret_cast<type>(pointer)
#else
    #define pointer_cast(type, pointer) (type)(pointer)
#endif

Maybe something like this? (untested, no compiler available, not using macros very often):

#ifdef __cplusplus
    #define pointer_cast(type, pointer) reinterpret_cast<type>(pointer)
#else
    #define pointer_cast(type, pointer) (type)(pointer)
#endif
十秒萌定你 2024-10-03 01:32:18

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

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

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

马里奥

The only solution I know is to do explicit casting:

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

Here both compilers are satisfied.
Also that remember, that for older compilers malloc may return char*.

hth

Mario

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文