C++ 为什么在reinterpet_cast中使用数值?

C++ 为什么在reinterpet_cast中使用数值?,c++,C++,我一直在看一些AOSP代码,我发现了这一点(来自5.0+的分支,在art/runtime/base/macros.h下) 其中Class是一个类,dex_cache是该类下的成员。它返回字段的偏移量,然后用作MemberOffset类的构造函数 我的问题是你到底为什么要硬编码里面的“16”?只取成员的地址并减去类的基址不是更有意义吗?你不能减去类的基址。您可以对对象的基址执行此操作,但您并没有任何基址。因此,宏将地址16转换为该基址 为什么不是0?林特会抱怨的。为什么不是1呢?结构对齐问题。这是

我一直在看一些AOSP代码,我发现了这一点(来自5.0+的分支,在art/runtime/base/macros.h下)

其中Class是一个类,dex_cache是该类下的成员。它返回字段的偏移量,然后用作MemberOffset类的构造函数


我的问题是你到底为什么要硬编码里面的“16”?只取成员的地址并减去类的基址不是更有意义吗?

你不能减去类的基址。您可以对对象的基址执行此操作,但您并没有任何基址。因此,宏将地址16转换为该基址


为什么不是0?林特会抱怨的。为什么不是1呢?结构对齐问题。

这是“试错编程”。。。可能有人听说用0代替16是不好的,所以他们想出了一个聪明的主意,把一个不同的数字放进去,看看它是否有效。也许它适用于某些体系结构。请注意,这里没有成员地址或基类地址,因为内存中没有对象——宏的第一个参数是类名,而不是对象。所以你建议的“修复”实际上是不可行的。我假设它是
16
而不是
0
的部分原因是
0
将是(静态可证明的)
nullptr
,因此编译可能会失败。而且,据我所知,在现代编译器中,
std::declval
应该不需要这种把戏。是的,但我想可能很接近。@KyleStrand你能推荐一些使用declval的实际代码吗?@M.M我错了
declval
(出于明显的原因)不允许ODR使用其返回值,也不允许比较内存地址计数。这一点很好。我没注意到他们实际上没有使用对象,只是想得到一个decltype。
#define OFFSETOF_MEMBER(t, f) \
  (reinterpret_cast<const char*>(&reinterpret_cast<t*>(16)->f) - reinterpret_cast<const char*>(16)) // NOLINT
MemberOffset(OFFSETOF_MEMBER(Class, dex_cache ));