It doesn't fully work.
The standard requires that offsetof should yield an integer constant expression.
Address-based calculations are never allowed to yield that although (intptr_t)&((T*)0)->T_member effectively is a compile-time known constant and if the compiler is squeamish about address 0, then at least
(intptr_t)&((T*)CONSTANT)->T_member - (intptr_t)(T*)CONSTANT) should be (gcc and clang allow expressions like the previous ones in some integer-constant-expression requiring contexts, but technically,
that's undefined behavior).
True integer constants can be detected, via magic such as:
#define CEXPR_EH(X) _Generic(1? (int*)0 : (void *)( 0ull*(X)), int*: 1, void*: 0)
and that macro says that the implementation™'s offsetof is better than yours:
#define CEXPR_EH(X) _Generic(1? (int*)0 : (void *)( 0ull*(X)), int*: 1, void*: 0)
#include <stddef.h>
struct a { int a, b; };
_Static_assert(CEXPR_EH(offsetof(struct a,b)),""); ✓
#define myoffsetof(T,M) ((long)&((T*)0)->M)
_Static_assert(CEXPR_EH(myoffsetof(struct a,b)),"Oops, I'm not special."); // ✗ fires
You may not like the standard-writers philosophy on this, but this is the way things are.
Clang and gcc implement offsetof via a special builtin:
#define offsetof(TYPE,MEMBER) __builtin_offsetof (TYPE, MEMBER)
offsetof. It merely specifies how it must behave. The actual definition is up to each implementation, and can vary one one implementation to another.offsetofis not used because it can easily lead to undefined behaviour.