为什么 offsetof 实现在 C 和 C++ 上有奇怪的不同?
Why offsetof implementations strangely differs on C and C++?
我打开 stddef.h
看到了这个:
#if defined _MSC_VER && !defined _CRT_USE_BUILTIN_OFFSETOF
#ifdef __cplusplus
#define offsetof(s,m) ((size_t)&reinterpret_cast<char const volatile&>((((s*)0)->m)))
#else
#define offsetof(s,m) ((size_t)&(((s*)0)->m))
#endif
#else
#define offsetof(s,m) __builtin_offsetof(s,m)
#endif
在 __cplusplus
的分支中(对于 C++ 编译器)有一个非常奇怪的实现,我认为它是多余的。 Else 分支(C 编译器的情况)具有更简单的字段偏移量计算。我测试了它,它有效。为什么在第一种情况下使用了这种奇怪的强制转换和类型限定符?
operator &
可以针对 m
的类型进行重载,因此 &((s*)0)->m)
会调用 operator &
而不是获取 m
的地址。
并且 const volatile
存在于 reinterpret_cast
的类型中,因此即使 m
是 const
and/or volatile
它也能正常工作.
请注意,在 C++11 中,std::addressof(x)
始终采用 x
的地址,而不管 operator &
重载。它的实现方式可能与您在问题中看到的类似。
我打开 stddef.h
看到了这个:
#if defined _MSC_VER && !defined _CRT_USE_BUILTIN_OFFSETOF
#ifdef __cplusplus
#define offsetof(s,m) ((size_t)&reinterpret_cast<char const volatile&>((((s*)0)->m)))
#else
#define offsetof(s,m) ((size_t)&(((s*)0)->m))
#endif
#else
#define offsetof(s,m) __builtin_offsetof(s,m)
#endif
在 __cplusplus
的分支中(对于 C++ 编译器)有一个非常奇怪的实现,我认为它是多余的。 Else 分支(C 编译器的情况)具有更简单的字段偏移量计算。我测试了它,它有效。为什么在第一种情况下使用了这种奇怪的强制转换和类型限定符?
operator &
可以针对 m
的类型进行重载,因此 &((s*)0)->m)
会调用 operator &
而不是获取 m
的地址。
并且 const volatile
存在于 reinterpret_cast
的类型中,因此即使 m
是 const
and/or volatile
它也能正常工作.
请注意,在 C++11 中,std::addressof(x)
始终采用 x
的地址,而不管 operator &
重载。它的实现方式可能与您在问题中看到的类似。