最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

container

互联网 admin 12浏览 0评论

container

offsetof

原型:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

作用:

得到MEMBER在TYPE类型的结构体中的偏移量。

解析:

((TYPE )0)->MEMBER :
在c语言中,地址也是用整数来表示的,这里的0,指的是地址,也可以理解为一个指向0地址的指针;(TYPE*)0就是把该地址转换成TYPE类型的的地址,也可以理解成指针转换,现有一个TYPE
的指针,指向的地址为0;那么这个语法连起来就是:找到了TYPE类型的结构体中MEMBER这个成员。

&((TYPE *)0)->MEMBER:
相较于上面,加了一个取地址运算符,这个得到了指向MEMBER这个成员的地址,因为MEMBER所在的struct起始地址是0,所以MEMBER的这个地址,其实就是MEMBER在结构体中的偏移量

container_of

原型:

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


参数:

  • ptr, 指向的是结构体中的一个成员
  • type, struct object
  • member, ptr指向的那个成员的名字,图中就是list

返回值:

return: 返回的是ptr指向的成员所在结构体的地址。

作用:

现有一个结构体obj,定义如上图所示。但是不知道obj的地址,知道的是obj里面的一个成员list的地址,记为ptr;container_of能够根据此信息获得obj的地址。

解析:

typeof( ((type *)0)->member ) :
(type *)0)->member得到了member这个成员,再用typeof取出它的类型。
const typeof( ((type *)0)->member ) *__mptr = (ptr); 这个是把ptr转换成了这个结构体类型的指针。

(type *)( (char )__mptr - offsetof(type,member) ):
我知道member的地址__mptr, 也能得到member在结构体中的偏移,那么相减就得到了结构体的地址。注意需要转换成char
来进行指针的减。

代码

#include <stdio.h>
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({                      \const typeof( ((type *)0)->member ) *__mptr = (ptr);    \(type *)( (char *)__mptr - offsetof(type,member) );})
struct s{char m1;char m2;char m3;s(char _1, char _2, char _3):m1(_1),m2(_2),m3(_3){}
};
int main()
{struct s *ss = new struct s('a','b','c');char* _m2 = (char*)(&ss->m2);struct s *temp = container_of(_m2, struct s, m2);printf("ss: %p, _m2:%p, temp:%p\n", ss, _m2, temp);//temp和ss指向的是同一个地址typeof(((struct s *)0)->m2) c;printf("%ld\n", (size_t) &((struct s*)0)->m2);//m2的偏移量
}

container

offsetof

原型:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

作用:

得到MEMBER在TYPE类型的结构体中的偏移量。

解析:

((TYPE )0)->MEMBER :
在c语言中,地址也是用整数来表示的,这里的0,指的是地址,也可以理解为一个指向0地址的指针;(TYPE*)0就是把该地址转换成TYPE类型的的地址,也可以理解成指针转换,现有一个TYPE
的指针,指向的地址为0;那么这个语法连起来就是:找到了TYPE类型的结构体中MEMBER这个成员。

&((TYPE *)0)->MEMBER:
相较于上面,加了一个取地址运算符,这个得到了指向MEMBER这个成员的地址,因为MEMBER所在的struct起始地址是0,所以MEMBER的这个地址,其实就是MEMBER在结构体中的偏移量

container_of

原型:

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


参数:

  • ptr, 指向的是结构体中的一个成员
  • type, struct object
  • member, ptr指向的那个成员的名字,图中就是list

返回值:

return: 返回的是ptr指向的成员所在结构体的地址。

作用:

现有一个结构体obj,定义如上图所示。但是不知道obj的地址,知道的是obj里面的一个成员list的地址,记为ptr;container_of能够根据此信息获得obj的地址。

解析:

typeof( ((type *)0)->member ) :
(type *)0)->member得到了member这个成员,再用typeof取出它的类型。
const typeof( ((type *)0)->member ) *__mptr = (ptr); 这个是把ptr转换成了这个结构体类型的指针。

(type *)( (char )__mptr - offsetof(type,member) ):
我知道member的地址__mptr, 也能得到member在结构体中的偏移,那么相减就得到了结构体的地址。注意需要转换成char
来进行指针的减。

代码

#include <stdio.h>
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({                      \const typeof( ((type *)0)->member ) *__mptr = (ptr);    \(type *)( (char *)__mptr - offsetof(type,member) );})
struct s{char m1;char m2;char m3;s(char _1, char _2, char _3):m1(_1),m2(_2),m3(_3){}
};
int main()
{struct s *ss = new struct s('a','b','c');char* _m2 = (char*)(&ss->m2);struct s *temp = container_of(_m2, struct s, m2);printf("ss: %p, _m2:%p, temp:%p\n", ss, _m2, temp);//temp和ss指向的是同一个地址typeof(((struct s *)0)->m2) c;printf("%ld\n", (size_t) &((struct s*)0)->m2);//m2的偏移量
}
发布评论

评论列表 (0)

  1. 暂无评论