【问题标题】:Safe conversion from integral value to pointer [duplicate]从整数值到指针的安全转换[重复]
【发布时间】:2020-11-14 14:26:58
【问题描述】:

如何安全地将无符号整数值(例如uint32_tuint64_t)转换为特定类型的指针?

例如我有:

using my_uint32_t = unsigned int;
using my_uint64_t = unsigned long long;

struct Sample {
    my_uint32_t address;
    my_uint64_t address_64;
};

Sample sample; /* Just for reference here */

struct TargetStruct {
   /* Some member variables goes here */
   ...
};

目标是访问分别存在于Sample.addressSample.address64TargetStruct 类型的对象。

我尝试使用:

TargetStruct * target = reinterpret_cast<TargetStruct *>( sample );

它有效,但安全吗?我知道规则说reinterpret_cast 应避免不安全,但有没有其他方法可以使其安全?

我无法查看我的“输入”——Sample 结构和它的内容——它只是简单地给出,但我必须以这种安全的方式使用存储在其中的数据......

我正在使用 C++20,所以我将避免使用 C 风格的强制转换...

【问题讨论】:

  • 使用std::uintptr_t from &lt;cstdint&gt;

标签: c++ pointers casting type-conversion c++20


【解决方案1】:

如何安全地将无符号整数值(例如 uint32_t、uint64_t)转换为特定类型的指针?

首先将整数转换为std::uintptr_t。此整数类型保证足够大以表示对象指针。 std::uintptr_t 然后可以重新解释为指针。

请注意,最初通过重新解释有效指针获得整数(足够大小)是唯一一种标准指定从整数到指针的转换结果值的情况。即:原来的指针值被复制出来了。

一个安全的例子:

int x;         // some object
int* ptr = &x; // pointer to that object
std::uintptr_t reinterpreted = reinterpret_cast<std::uintptr_t>(ptr);
// following sanity check might fail in theory on systems
// where pointer is larger than 64 bits
assert(reinterpreted <= std::numeric_limits<my_uint64_t>::max());
my_uint64_t reinterpreted64 = reinterpreted;
// now we have a pointer in my_uint64_t

// conversion back
std::uintptr_t reinterpreted2 = reinterpreted64;
int* ptr_again = reinterpret_cast<int*>(reinterpreted2);
assert(ptr == ptr_again); // this is guaranteed to pass

【讨论】:

  • 转换为reinterpret_cast,或static_cast,或...?
  • @MooingDuck 如果你的意思是整数到std::uintptr_t,那么要么是隐式转换,要么是static_cast,如果你想明确的话。其他转换(整数和指针之间)是重新解释强制转换。
  • 所以这意味着重新解释两次? uintptr_t temp = reinterpret_cast&lt;uintptr_t&gt;( sample.address ); 然后TargetStruct * = reinterpret_cast&lt;TargetStruct *&gt;( temp ); ?
  • @MartinKopecký:你不应该需要第一个。 sample.address 应该已经是 std::uintptr_t。不能保证指针可以存储为任何其他整数类型。如果指针是 80 位呢?
  • @MartinKopecký 没有。只有一个重新解释。我添加了转换为my_uint64_t 的额外步骤来展示如何操作。也就是说,始终使用 std::uintptr_t 而不是转换为 my_uint64_t 并返回可能是有意义的,理论上可能会丢失正确的值。
猜你喜欢
  • 2010-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多