免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5511 | 回复: 5
打印 上一主题 下一主题

关于container_of 第一行的__mptr作用的总结 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-11-14 22:52 |只看该作者 |倒序浏览
每次看到container_of这个宏,都会对它的第一句话const typeof( ((type *)0)->member ) *__mptr = (ptr);产生疑问,今天终于下狠心解决了一下,去网上查了很多的资料,发现解释的都很牵强,不完全,大概分为两种类型,再此做下介绍:
1.检查ptr的类型是否为member类型(这个说的不明不白,但是我倾向于这种,下面会有解释)
2.第二个如下:(复制来的)

比如
#define min(x,y) ((x) < (y) ? (x) : (y))

当调用时用的是min(a++,b++)的时候,a和b的值就不对了(可能加了两次)。


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

就没有这个问题。

  复制完毕,这个比较有教育意义了,我也学习了,但是跟container_of这个宏还是不怎么沾边,毕竟ptr只用了一次,用来解释这个问题就牵强了

  以下是我的理解:现在解释第一种类型,给人的第一个想法是ptr这个参数是错误的,不符合type->member,但是不会对结果产生任何影响,也不影响,(type *)((char *)__mptr - offsetof(type, member)); 这句话的运行,所以认为这句话是无用的。
   大家主要把注意力放在了ptr这个参数上了,实际上 const typeof( ((type *)0)->member ) *__mptr = (ptr); 这句话把三个参数都检查了,试想如果member是type结构体里的成员,但是member不是ptr所指的类型,换句话说ptr是正确的但是member是错误的,(type *)((char *)__mptr - offsetof(type, member)); 显然结果是错误的。但是这句话编译器检查不出来,编译器不报错发出任何警告和错误,警告也是一种提示方式,因为c语言只能静态检查类型,所以只能通过编译器获取‘数据类型’的错误。虽然是警告,但是内核正常情况下发出任何警告。
   还有一个原因是表明const typeof( ((type *)0)->member ) *__mptr = (ptr); 这句话确实是检查参数用的,试想如果内核开发者真的想赋值保存ptr他会怎么做?
   应该会const typeof( ((type *)0)->member ) *__mptr = (((type *)0)->member)(ptr); 会强制类型转换一下防止参数传的类型不符而产生的警告,还是那句话,内核正常应用不会产生警告,它会扼杀一切不规范的苗头,这点可以从下一句的offsetof(type,member)的实现中可以看出
   #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
    这个宏返回的是size_t类型,为什么呢?直接返回地址类型也对啊,不会影响结果的运行,但是这样使用是不规范的,会产生警告,内核是不允许的。
   这个警告也许算内核开发人员的善意的提示吧。
   最后声明一点,肯定会有人说,警告而已,真正做项目的时候谁看警告啊,你说的是对的,换个角度想,也算是我煽情臭屁一下,开发内核的人不是你们公司那种档次的人,如果他们拿出满天警告乱飞的操作系统,会让微软那波人鄙视地- -!!那样的操作系统你敢用?

评分

参与人数 1可用积分 +6 收起 理由
瀚海书香 + 6 多谢分享!

查看全部评分

论坛徽章:
0
2 [报告]
发表于 2011-11-14 22:53 |只看该作者
求加精啊!!!!!

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
3 [报告]
发表于 2011-11-15 00:28 |只看该作者

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
4 [报告]
发表于 2011-11-15 07:47 |只看该作者
回复 3# embeddedlwp
这个强制转换类型是不会出错的,顶多就是个warning,也就是说不会出现你说的情况:
如图:

因为强制转换的话,代码应该是没有错误的。如下图:

论坛徽章:
0
5 [报告]
发表于 2011-11-15 09:41 |只看该作者
你要加精,偶的咋办。
embeddedlwp 发表于 2011-11-15 00:28



    你说的是我刚开始我在网上找的答案的第一种类型,说的对,但是很含糊,不完全,具体的请仔细看我下面的分析,一看就没仔细看这个帖子 = =!!

论坛徽章:
0
6 [报告]
发表于 2011-11-15 09:53 |只看该作者
说实在的这个宏大多数人还是不明白第一行的作用,这个宏的实现很巧妙,但是看不懂的人很少,就那一行代码有什么可不懂的? 网上那些人就解释了这两行代码的含义,没有解释为什么这样做,特别是复制粘贴党,这样的帖子看多了就有股气,跟玩游戏秀操作的人一样,看着挺好屁用没有
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP