【问题标题】:Convert pointer to int and back to typed object将指针转换为 int 并返回到类型化对象
【发布时间】:2013-03-24 18:24:56
【问题描述】:

我需要一种简单的方法将指针转换为 int,然后再返回指针。我需要它作为 int 的可移植性,因为 int 在我的项目中比指针更容易携带。

启动播放器并返回指针:

SoundPlayer* player = new FxPlayerTiny();
return (int)player; // this works, but is it correct?

使用指针 int 停止播放器:

FxPlayerTiny* player = static_cast<FxPlayerTiny*>((int*)num); // this gives me an error
FxPlayerTiny* player = (FxPlayerTiny*)((int*)obj); // this works, but is it correct?
delete player;

【问题讨论】:

  • 呃,int 怎么携带更方便?不,那个代码是不安全的。
  • 如果你真的真的必须转换成不透明的东西,至少使用void*
  • 为什么int比指针更容易使用?这听起来不对。此外,不能保证整个指针适合 int。 C 提供了 intptr_t(大多数 C++ 实现也提供了它),它是一个整数类型,保证足够大以容纳一个指针。使用 reinterpret_cast 在两者之间切换。
  • @James:不能保证intptr_tuinptr_t 存在;在指针大于支持的最宽整数的实现上,它们不会。但我从未听说过这样的实现。此外,这些类型是在 C99 中引入的,因此较旧的 C 编译器(和 Microsoft 的)可能不支持它们。
  • 修复您的项目,使其能够直接处理指针。

标签: c++ visual-c++ pointers casting


【解决方案1】:

最好的办法是修复您的项目,以便它可以处理指针。整数和指针是两个不同的东西。您可以来回转换,但如果您不小心,此类转换可能会丢失信息。

将指针值转换为int 并再次转换回来很容易丢失信息,具体取决于实现和底层平台。例如,有系统对int 小于一个指针。如果您有 32 位 ints 和 64 位指针,那么将指针转换为 int 并再次返回几乎肯定会给您一个无效的指针。

很有可能longunsigned long 的宽度足以容纳转换后的指针值而不会丢失信息;我从来没有在一个没有它的系统上工作过。 (就个人而言,我更喜欢无符号类型,但不是出于任何真正好的理由;两者都应该同样有效。)

所以你可以写,例如:

SoundPlayer* player = new FxPlayerTiny();
return reinterpret_cast<unsigned long>player;

并使用reinterpret_cast,SoundPlayer*&gt;unsigned long 值转换回指针。

较新的实现提供了 typedef uintptr_tintptr_t,它们是无符号和有符号整数类型,保证在往返指针到整数到指针的转换中正常工作。它们是在 C99 中引入的,可选&lt;stdint.h&gt; 标头中定义。 (指针大于 any 整数类型的实现不会定义它们,但这种实现很少见。)C++ 在 2011 标准中采用它们,在 &lt;cstdint&gt; 标头中定义它们。但 Microsoft Visual C++ 从 2010 版本开始支持它们。

此保证仅适用于普通指针,不适用于函数指针或成员指针。

所以如果你必须这样做,你可以这样写:

#include <cstdint>
SoundPlayer* player = new FxPlayerTiny();
return reinterpret_cast<std::uintptr_t>player;

但首先,请考虑这一点。 new FxPlayerTiny() 给你一个指针值,你会想要一个指针值。如果可能,请将其保留为指针。将其转换为整数意味着您必须决定使用几种技术中的哪一种,并且您必须跟踪整数值应该表示的指针类型。如果你犯了一个错误,要么使用了一个不够大的整数类型,要么忘记了你存储的指针类型,编译器可能不会警告你。

也许您有充分的理由需要这样做,但如果您可以将指针存储为指针,您的生活会轻松很多。

【讨论】:

  • Microsoft Visual C++ 支持uintptr_tintptr_tptrdiff_t(他们总是被遗忘的合作伙伴)至少从 2008 年版本开始,可能更久。 :)
  • ptrdiff_t 自 1989 年以来一直是标准配置,但很高兴知道它们也支持 [u]intptr_t
【解决方案2】:

不建议使用 int 来实现可移植性,尤其是因为 sizeof (int)sizeof (void*) 可能不同(例如在为 Windows x64 编译时)。 如果用户界面需要整数,最好使用指针表并通过索引访问它们。

但是,如果您想将指针转换为整数,反之亦然,那么简单的转换就足够了,但它是一样的,如果sizeof *int) == sizeof (void*)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-06
    • 2023-04-09
    • 1970-01-01
    • 2011-04-03
    相关资源
    最近更新 更多