c ++ reinterpret_cast一个整数

时间:2018-07-18 06:33:57

标签: c++ pointers reinterpret-cast offsetof

我遇到了以下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的参数。

3 个答案:

答案 0 :(得分:1)

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<point*>(16)->y的另一种方式可能是这样的:point * myPt = 16u;我们知道16不是有效地址,但是编译器不是,只要我们不尝试阅读我们指向的地址,我们可以。

接下来,我们可以将所有&reinterpret_cast<point*>(16)->y简化为:&myPt->y。从上面我们知道y是@ offset 0x4,因为myPt是16:16 + 0x4 = 20

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

答案 1 :(得分:0)

来自reference

  

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

因此,reinterpret_cast<>的部分设计目的就是要做到这一点。

答案 2 :(得分:0)

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

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

有关更多信息,请参见panelWidth