hust_jixing 2015-12-28 01:38 采纳率: 0%
浏览 1737
已采纳

关于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 *类型, 就我目前的知识来看这种操作好鸡肋, 内核这样做是适应编译器的操作“习惯”吗? 还是说有其它的“难言之隐“?有大神能帮忙解答一下吗? 
  • 写回答

1条回答 默认 最新

  • 不够努力的撸舍 2016-02-01 06:39
    关注

    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表达式,都不会有副作用。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 易语言把MYSQL数据库中的数据添加至组合框
  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况