免费注册 查看新帖 |

Chinaunix

广告
  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4878 | 回复: 14
打印 上一主题 下一主题

Linux 内核中container_of宏中的指针转换问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-08-31 09:31 |只看该作者 |倒序浏览
在Linux中有一段宏:
  1. #define container_of(ptr, type, member) ({ \
  2. const typeof( ((type *)0)->member ) *__mptr = (ptr); \
  3. (type *)( (char *)__mptr - offsetof(type,member) );})
复制代码
而上面宏中的offsetof宏的定义如下:
  1. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
复制代码
上面的代码我有以下几个疑问:
1.offseof 中的
  1. size_t) &((TYPE *)0)->MEMBER
复制代码
为什么要强制转换成 size_t 类型的?
2.既然offseof的返回类型是size_t类型的,那(type *)( (char *)__mptr - offsetof(type,member) 中为什么又要把__mptr的类型转换成 char *  呢?

论坛徽章:
0
2 [报告]
发表于 2011-08-31 10:09 |只看该作者
size_t在X86-64下就是unsigned long类型,一个偏移量强制转换成这个类型应该容易理解。

而__mptr指针是传进来的member类型的,我们要对他的值做算术操作就需要转换成char *类型,为了确保对该地址做加减操作的步长为1,即地址减1就是减1,而不是减去该指针对应结构体的大小。最后再转换为type类型的指针。

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
3 [报告]
发表于 2011-08-31 10:09 |只看该作者
回复 1# 狼之鹏
这个宏最终是取地址的啊,指针是可以进行加减的

论坛徽章:
22
丑牛
日期:2014-08-15 14:32:0015-16赛季CBA联赛之同曦
日期:2017-12-14 15:28:14黑曼巴
日期:2017-08-10 08:14:342017金鸡报晓
日期:2017-02-08 10:39:42黑曼巴
日期:2016-11-15 15:48:38CU十四周年纪念徽章
日期:2016-11-09 13:19:1015-16赛季CBA联赛之同曦
日期:2016-04-08 18:00:03平安夜徽章
日期:2015-12-26 00:06:30程序设计版块每日发帖之星
日期:2015-12-03 06:20:002015七夕节徽章
日期:2015-08-21 11:06:17IT运维版块每日发帖之星
日期:2015-08-09 06:20:002015亚冠之吉达阿赫利
日期:2015-07-03 08:39:42
4 [报告]
发表于 2011-08-31 10:53 |只看该作者
size_t 在不同架构的计算机不一样的,这里是用做一个计数的变量,所以用size_t
char* 是为了确保内存加的数值等于指针上加的数值,就是说指针加1就是内存地址加1.

举个例子:
char *p = 0x8000;
p++;  <=== p: 0x8001

int *p = 0x8000;
p++; <==== p: 0x8004

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
5 [报告]
发表于 2011-08-31 13:34 |只看该作者
回复 4# amarant
这个例子举得多少有点欠妥啊

论坛徽章:
22
丑牛
日期:2014-08-15 14:32:0015-16赛季CBA联赛之同曦
日期:2017-12-14 15:28:14黑曼巴
日期:2017-08-10 08:14:342017金鸡报晓
日期:2017-02-08 10:39:42黑曼巴
日期:2016-11-15 15:48:38CU十四周年纪念徽章
日期:2016-11-09 13:19:1015-16赛季CBA联赛之同曦
日期:2016-04-08 18:00:03平安夜徽章
日期:2015-12-26 00:06:30程序设计版块每日发帖之星
日期:2015-12-03 06:20:002015七夕节徽章
日期:2015-08-21 11:06:17IT运维版块每日发帖之星
日期:2015-08-09 06:20:002015亚冠之吉达阿赫利
日期:2015-07-03 08:39:42
6 [报告]
发表于 2011-08-31 13:38 |只看该作者
回复 5# Godbach

呵呵,例子是为了说明C语言里指针加减操作的实质,估计LZ就是没有搞明白这点才不知道为什么要转换成char *类型后进行操作

论坛徽章:
0
7 [报告]
发表于 2011-08-31 22:25 |只看该作者
谢谢各位,我明白了。
但是我还有一个疑问:
在offsetof宏中的是一个 char* 类型的减去一个size_t类型的,在这个过程中是否会发现强制类型转换,因为它们的类型不一样啊。如果不会,为什么?

论坛徽章:
0
8 [报告]
发表于 2011-08-31 22:26 |只看该作者
回复 6# amarant


   谢谢各位,我明白了。
但是我还有一个疑问:
在offsetof宏中的是一个 char* 类型的减去一个size_t类型的,在这个过程中是否会发现强制类型转换,因为它们的类型不一样啊。如果不会,为什么?

论坛徽章:
22
丑牛
日期:2014-08-15 14:32:0015-16赛季CBA联赛之同曦
日期:2017-12-14 15:28:14黑曼巴
日期:2017-08-10 08:14:342017金鸡报晓
日期:2017-02-08 10:39:42黑曼巴
日期:2016-11-15 15:48:38CU十四周年纪念徽章
日期:2016-11-09 13:19:1015-16赛季CBA联赛之同曦
日期:2016-04-08 18:00:03平安夜徽章
日期:2015-12-26 00:06:30程序设计版块每日发帖之星
日期:2015-12-03 06:20:002015七夕节徽章
日期:2015-08-21 11:06:17IT运维版块每日发帖之星
日期:2015-08-09 06:20:002015亚冠之吉达阿赫利
日期:2015-07-03 08:39:42
9 [报告]
发表于 2011-09-01 08:05 |只看该作者
回复 8# 狼之鹏


    不会,你可以自己动手写写看看

论坛徽章:
0
10 [报告]
发表于 2011-09-01 09:41 |只看该作者
回复  amarant


   谢谢各位,我明白了。
但是我还有一个疑问:
在offsetof宏中的是一个 char* 类型 ...
狼之鹏 发表于 2011-08-31 22:26


char *类型的指针做算术运算,实际上就是对该指针的值做运算,指针的值就是一个地址值,在32位系统下就是int类型,而后面的size_t在32位下就是unsigned int类型,他们在做算术运算的时候是会发生类型转换的,但那是编译器默认进行的,不会对结果和精度造成影响。

具体的转换方式和规则可以参考ANCI C标准手册的6.2.1.1节算术转换和6.2.1.5节寻常算术转换,大概的意思就是“当执行算术运算的时候,操作数类型如果不同(如上面的Int和unsigned int),就会发生转换。数据类型一般是向着浮点精度更高、长度更长的方向转换,整型数如果转换为signed不会丢失信息,就转换为signed类型,否则转换为unsigned。”
实际的手册上说明了更多内容。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP