Пример реализации MSVC:
#define offsetof(s,m) \
(size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))
// ^^^^^^^^^^^
Как можно видеть, он разыменовывает нулевой указатель, который обычно вызывает неопределенное поведение. Это исключение из правила или что происходит?