Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rationale behind the container_of macro in linux/list.h

In the implementation of linux kernel lists in /include/linux/list.h, what is the rationale behind the first line (pasted below) of the container_of macro?

const typeof( ((type *)0)->member ) *__mptr = (ptr); 

In a sample code of mine, I removed this line and changed the definition to

#define container_of(ptr, type, member) ({                      \      (type *)( (char *)ptr - offsetof(type,member) );}) 

and my code still showed expected results. Is the first line redundant then? Or does it have some hidden trap that I am not aware of?

The code I found at Faq/LinkedLists

/**  * container_of - cast a member of a structure out to the containing structure  * @ptr:        the pointer to the member.  * @type:       the type of the container struct this is embedded in.  * @member:     the name of the member within the struct.  *  */ #define container_of(ptr, type, member) ({                      \         const typeof( ((type *)0)->member ) *__mptr = (ptr);    \         (type *)( (char *)__mptr - offsetof(type,member) );})  #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 
like image 866
woodstok Avatar asked May 21 '11 18:05

woodstok


1 Answers

It adds some type checking. With your version, this compiles fine (without warning):

struct foo { int bar; };  ....  float a; struct foo *var = container_of(&a, foo, bar); 

With the kernel version, the compiler reports:

warning: initialization from incompatible pointer type 

Good explanation of how the macro works: container_of by Greg Kroah-Hartman.

like image 112
Mat Avatar answered Sep 20 '22 16:09

Mat