C++和box2d:userdata将int强制转换为void*

C++ and box2d: userdata cast int to void*

本文关键字:转换 void int box2d userdata C++      更新时间:2023-10-16

我对box2d很陌生,我正在尝试使用b2body对象中的userdata(类型为void*)字段来存储int值(一个枚举值,这样我就知道对象的类型)。

现在我正在做这样的事情:

int number = 1023;
void* data = (void*)(&number);
int rNumber = *(int*)data;

我得到了正确的值,但正如我一直在阅读的关于铸造到void的文章,它是不可移植或不推荐的。。。我的代码是跨平台的吗?它是行为定义的还是实现依赖的?

谢谢!

转换为void *是可移植的。不建议使用,因为您正在失去类型安全性。任何东西都可以放入void *,任何东西都能取出。这样更容易射中自己的脚。否则void *是好的,只要你小心和格外小心。

您实际上不是将int强制转换为void*,而是将int*强制转换为void*,这完全不同。

指向任何类型的指针都可以存储在void*中,并再次强制转换回相同的类型。这是有保证的。

转换为任何其他类型都是不可移植的,因为语言标准没有规定不同的指针必须具有相同的大小或以相同的方式工作。只是void*必须足够宽才能包含它们。

void*的一个问题是,您需要知道(跟踪)它最初是什么类型,以便正确地转换它。如果它最初是一个float,而你将其大小写为int,编译器就会相信你的话

为了避免这种情况,您可以为包含类型的数据创建一个包装器,这样您就可以始终将其强制转换为正确的类型。

编辑:您还应该养成使用C++铸造样式而不是C的习惯,即reinterpret_cast

void*在某种程度上是过去的遗迹(ISO C),但非常方便。只要你小心地前后转换你想要的类型,你就可以安全地使用它。考虑其他替代方案,如c++类系统或重载函数

无论如何,你会有更好的cast运算符,有些时候没有其他方法(void*),有些时候它们太方便了。

它可能导致不可移植的代码,这不是因为强制转换系统,而是因为有些人很想用它们进行不可移植操作。最大的问题在于(void*)是一个与内存地址一样大的地址,在许多平台中,它恰好也是平台整数的长度。

然而,在一些罕见的例外情况下,size(void*)!=大小(int)

如果你试图用它们进行某种类型的操作/魔术,而不返回到你想要的类型,你可能会遇到问题。你可能会惊讶于我见过多少次有人想把一个整数存储到一个空*指针中

要回答您的问题,是的,这样做是安全的。

为了回答你没有问的问题,这个void指针并不意味着要保留int。Box2D有一个指针可以让你指向游戏引擎中的Entity对象,这样你就可以将游戏中的实体与物理模拟中的b2Body关联起来。当一个b2Body与另一个b2Body交互时,它允许您更容易地对实体之间的交互进行编程。

所以你不应该只是把一个枚举放在这个空白中。您应该将其直接指向由该b2body表示的游戏对象,该对象中可能有一个枚举。