in MSVC, offsetof implemented as:
#define offsetof(s,m) ((size_t)&reinterpret_cast<char const volatile&>((((s*)0)->m)))
My question is:
why
reinterpret_cast?why
volatile?why
size_t, notptrdiff_t?
in MSVC, offsetof implemented as:
#define offsetof(s,m) ((size_t)&reinterpret_cast<char const volatile&>((((s*)0)->m)))
My question is:
why reinterpret_cast?
why volatile?
why size_t, not ptrdiff_t?
&reinterpret_cast<char const volatile&>(expr) is also the code used to implement std::addressof. std::addressof is necessary because C++ allows overloading the unary-& operator, but the actual library function can't be used here prior to C++17, when it is marked constexpr.
size_t rather than ptrdiff_t because that's what the standard says it has to return.
Edit: while technically the standard doesn't directly specify this case, in practice compilers are forced to cover it due to other logic and historical practice.
why reinterpret_cast?
reinterpret_cast<>() is the only way to convert a pointer to a size_t
why volatile?
volatile prevents the optimizer to optimize away the expression (((s*)0)->m)).
why size_t, not ptrdiff_t?
offsetof() returns an offset, not the number of elements between two pointers.