【问题标题】:c++ reinterpret_cast a integerc++ reinterpret_cast 一个整数
【发布时间】:2018-12-25 23:05:32
【问题描述】:

我遇到了以下 c++ 代码:

 #define OFFSETOF_MEMBER(t, f) \
  (reinterpret_cast<uintptr_t>(&reinterpret_cast<t*>(16)->f) - static_cast<uintptr_t>(16u)) // NOLINT

其中 t 是一个类型,f 是一个字段名。我想知道为什么我们可以将整数 16 作为 reinterpret_cast 的参数。

【问题讨论】:

  • 请注意,这是未定义的行为。 C++ 确实有offset_of,这是每个实现都定义的宏;一些实现会这样定义它。
  • ^ 宏是 offsetof ,在非标准布局类上使用它是 UB

标签: c++ pointers reinterpret-cast offsetof


【解决方案1】:

来自reference

3) 任何整数或枚举类型的值都可以转换为指针类型。 [...]

所以,reinterpret_cast&lt;&gt; 的部分目的就是为了做到这一点。

【讨论】:

    【解决方案2】:

    整数 16 只是一个内存地址。表达式reinterpret_cast&lt;t*&gt;(16) 仅表示“将地址16 处的对象解释为t 类型”,但您知道该地址处没有t 对象。理论上,16 可以替换为任何 4x(32 位)或 8x(64 位)整数。如果选择0,宏可以简化为:

    #define OFFSETOF_MEMBER(t, f) \
      (reinterpret_cast<uintptr_t>(&reinterpret_cast<t*>(0)->f))
    

    更多信息请参见offsetof

    【讨论】:

    • 但请注意,此代码深入未定义的行为。在标准库中定义offset_of 的原因是标准库附带了一个编译器,并且可以利用该编译器的已知行为。这不是一个好的、可移植的代码示例。
    【解决方案3】:

    16 是我们分配给指针的地址,它可以让我们计算指定成员的偏移量。指针的地址只是一个数字,因此我们可以滥用这一事实来获取有关我们的结构/类的信息。

    假设我们有一个结构:

    struct point { 
        //Assuming 32-bit integer sizes. 
        //For 64-bit integersizes, 0x0, 0x8, 0x10 for the integer offsets
        int x; //Offset 0x0
        int y; //Offset 0x4
        int z; //Offset 0x8
    }; static_assert(sizeof(point) == 12 /* or 0xC in hex */);
    

    我们使用宏:

    OFFSETOF_MEMBER(point, y);
    

    展开宏,我们得到:

    (reinterpret_cast<uintptr_t>(&reinterpret_cast<point*>(16)->y) - static_cast<uintptr_t>(16u)
    

    表达reinterpret_cast&lt;point*&gt;(16)-&gt;y 的另一种方式可能是这样的:point * myPt = 16u; 我们知道 16 不是有效地址,但编译器不会,只要我们不尝试读取地址,我们'指向,我们没事。

    接下来,我们可以将所有&amp;reinterpret_cast&lt;point*&gt;(16)-&gt;y 简化为:&amp;myPt-&gt;y。我们从上面知道 y 是 @offset 0x4,并且由于 myPt 是 16:16 + 0x4 = 20

    然后我们有reinterpret_cast&lt;uintptr_t&gt;(20u) - static_cast&lt;uintptr_t(16u)20 - 16,这给了我们y的偏移量,即0x4。

    【讨论】:

      猜你喜欢
      • 2011-06-17
      • 2011-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多