Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why this 0 in ((type*)0)->member in C?

Tags:

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?

like image 689
lxgeek Avatar asked Dec 05 '12 12:12

lxgeek


2 Answers

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.

like image 60
cnicutar Avatar answered Sep 20 '22 12:09

cnicutar


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.

like image 40
Some programmer dude Avatar answered Sep 18 '22 12:09

Some programmer dude