0

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?

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
Chen Li
  • 4,824
  • 3
  • 28
  • 55
  • `size_t` because the standard says so. Don't you worry about the rest, let STL worry about that. – Baum mit Augen Jul 31 '17 at 00:00
  • 2
    One reason that `offsetof` is in the standard C library is that it can't be implemented portably. So the answer to "why is it written that way" is simply "because it works". – Pete Becker Jul 31 '17 at 00:03
  • See also https://stackoverflow.com/questions/6494591/how-can-i-reliably-get-an-objects-address-when-operator-is-overloaded/6495205#6495205 – o11c Jul 31 '17 at 00:04

2 Answers2

-2

&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.

o11c
  • 15,265
  • 4
  • 50
  • 75
-3
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.

Michaël Roy
  • 6,338
  • 1
  • 15
  • 19