The container_of() macro in the Linux kernel is defined as:
#define container_of(ptr, type, member) ({ \
const typeof( ((type*)0)->member) * __mptr =(ptr);\
(type*)( (char*)__mptr - offsetof(type,member) );})
Why does this use ((type*)0)->member, not (type*)->member?
Simply because
(type*)->memberwould be invalid syntax, thustypeofwould be impossible. So it uses aNULLpointer, which it doesn’t dereference anyway – it’s used just sotypeofcan refer to the member.How this works:
The
typeoftrick is used to declare a pointer of the type of the member. This pointer gets is initialized with the pointer passed by the callerThe 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
typeofand just doptr - offsetof. We’re casting it tochar *anyway, right ? In that case you could pass anything asptrand the compiler won’t say a thing. So the wholetypeofthings is there for (rudimentary) type checking.