跳至主要内容

container_of

Linux常用container_of宏从成员变量提取整个结构体的首地针,这个宏的定义如下:

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

typeof是gcc的一个扩展,用于确定一个变量的类型,有点像C++的RTTI,常用于表达式内的语句,在定义宏时,如果需要临时变量,可以这样做:
#define max(a,b) \
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })
它可以保证我们定义的变量_a/_b与宏传入的变量a/b类型匹配,而不会产生编译器告警。

因此container_of的第一行就是定义一个与member类型匹配的变量__mptr,赋值后,__mptr为宏参数中的待转换指针,因为只是类型转换,不涉及数据读写,((type*)0)是没有任何副作用的。

第二行用__mptr减去member变量在type中的偏移,这样便可实际访问到ptr相同偏移,也即type的实际首地址了。offsetof有两种定义:

#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif

__compiler_offsetof即__builtin_offsetof,__builtin_offsetof可能是gcc內建的支持(见gcc源码c-parser.c),
从后一种实现方式可以明显看到这一技巧,假定一个从0地址开始的结构体,取其成员member的地址正是结构体内的偏移。

评论

此博客中的热门博文

反转剧

这两天明显感到天气转冷,呱呱的家里也已经下起了大雪,南京则是阴冷潮湿,让人没有了出行的欲望。没想到躲在被子里看反转剧也成了度过寒冬的一剂良药。在PPLive越来越让人失望的时候,PPStream横空出世,虽然广告仍是少不了的主题,但从视频质量和播放连续性上来说都超过PPLive,实为居家必备之良品(由此可见,新事物一定会战胜旧事物......)。韩国的反转剧最近似乎比较流行,称之为反转剧就在于其结果总是让人出乎意料,不合常理,其间又不乏各种搞怪搞笑的镜头,各种当红帅哥美女也一定让DDMM们爱不释手,20~30分钟一集的剧情一改韩剧拖沓的风貌,想看就看,容易切入。 反转剧,今天你看了吗?

from cpp to java

when i start to study java with a cpp background, i find it is very difficult to convert my mind. i always think how some features in cpp was implemented in java, this give me a little reject to java language. though java is born from c, i think they still have different applicable domains, so try to study both is good for me, and java is a pure OO language, i believe it will give me a better understanding on OOD.

biblioscape, endnote, no, none of them

endnote在与word2003搭配时经常占据严重的CPU,非常不好用。今天听说biblioscape好,下之,唉,高兴的日子总是那么短暂,BUG一堆。它只支持rtf格式的转换,在word里format时,还要转为rtf格式后再转回来。甚至在重复转换过程中也产生了不一致,可能它在RTF和DOC之间的转换没有那么精确吧。好想用latex排,不过时间紧迫,现在懒得去学了。 都不用了,还是手工输入参考文献罢了。也许,open office?下一个先。