关于linux kernel中的container_of宏的困惑

#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})

最近在看linux kernel中的链表操作, 看到了如上这个宏, 其实表达的意思很简单, 但是他要用一个__mptr来指向ptr甚是不解?实测如下宏也是可行的:
#define container_of(ptr, type, member) ({ \
(type *)( (char *)ptr - offsetof(type,member) );})

内核用一个临时const变量来存储ptr是为什么啊? 并且第一步还要强行获得ptr的对象类型, 第二步又将mptr强转成char *类型, 就我目前的知识来看这种操作好鸡肋, 内核这样做是适应编译器的操作“习惯”吗? 还是说有其它的“难言之隐“?有大神能帮忙解答一下吗? 
0

1个回答

GNU C把包含在括号里的复合语句看做是一个表达式,称为语句表达式,它可以出现在任何允许表达式的地方。我们可以在语句表达式中使用原本只能在复合语句中使用的循环变量、局部变量等

例如int aa = ({3; 43-5;});使用不支持GNU C的编译器会报错,而使用gcc会得到aa为38
利用GNU C的这种特性,我们可以避免一些宏定义产生副作用,如使用

#define min_t(type,x,y) \
({type x=(x); type __y=(y);x<__y?__x:__y})
代替

#define min(x,y) ((x)<(y)?(x):(y))
可避免传入min(a++,b++)产生副作用

所以, const typeof( ((type *)0)->member ) *__mptr = (ptr);是为了确保不会得到任何ptr表达式,都不会有副作用。

1
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!