The container_of() macro in the Linux kernel is defined as:
#define container_of(ptr, type, member) ({ \\
const typeof( ((type*)0)->member) * __mp
Because type*
is a type and not a valid instance of the structure.
The pointer to zero is used to get a proper instance, but as typeof
is resolved at compile-time and not at run-time the address used in the pointer doesn't have to be a proper or valid address.
Why this is ((type*)0)->member, not (type*)->member
Simply because (type*)->member
would be invalid syntax, thus typeof
would be impossible. So it uses a NULL
pointer, which it doesn't dereference anyway - it's used just so typeof
can refer to the member.
How this works:
The typeof
trick is used to declare a pointer of the type of the member. This pointer gets is initialized with the pointer passed by the caller
The offset of that member in the struct is subtracted from the address of the pointer: this yields the address of the containing object
Subtler issue: why not get rid of typeof
and just do ptr - offsetof
. We're casting it to char *
anyway, right ? In that case you could pass anything as ptr
and the compiler won't say a thing. So the whole typeof
things is there for (rudimentary) type checking.