Linux / offsetof 和 container_of

/** @member    TYPE    : 结构体原型。*            MEMBER  : 结构体成员。  */
#define offsetof(TYPE , MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

 

(2)文件路径:/ include / linux / stddef.h

(3)作用

返回指定类型(TYPE)的成员(MEMBER)在该结构体内的偏移量。

(4)解析

         A、(TYPE *) 0

                  将以地址 0 为开始的,大小为 sizeof(TYPE) 的内存块按照 TYPE 进行看待。注意,这里只是看待,并没有进行读                取!这就保证了代码执行到这里并不会报错!

         B、((TYPE *) 0) -> MEMBER

                  看看 MEMBER 成员,还是没有读取。

         C、&(((TYPE *) 0) -> MEMBER)

                 看看 MEMBER 成员地址,还是没有读取。因为结构体的首地址为0,所以得到的 MEMBER 的首地址就是该成员相对            于结构体首地址的偏移量。

         D、(size_t)&(((TYPE *)0) -> MEMBER)

                 将该地址转为 size_t 类型。

          在32位系统中,size_t 的原型是 unsigned int

          在64位系统中,size_t 的原型是 unsigned long

(5)栗子

#include #define offsetof_t(TYPE , MEMBER) ((size_t)&(((TYPE *)0)->MEMBER))struct stest
{char    c;int     i;float   f;double  d;
};int main()
{int pos_c = offsetof_t(stest , c);int pos_i = offsetof_t(stest , i);int pos_f = offsetof_t(stest , f);int pos_d = offsetof_t(stest , d);std::cout << "stest::c 的偏移量:" << pos_c << std::endl;std::cout << "stest::i 的偏移量:" << pos_i << std::endl;std::cout << "stest::f 的偏移量:" << pos_f << std::endl;std::cout << "stest::d 的偏移量:" << pos_d << std::endl;return 0;
}

结果:

/** @member    ptr    结构体成员的地址。*            type   结构体原型。*            member 结构体成员。*/
#define container_of(ptr, type, member) ({			\const typeof( ((type *)0)->member ) *__mptr = (ptr);	\(type *)( (char *)__mptr - offsetof(type,member) );})

(2)文件路径:/ include / linux / kernel.h

(3)作用:通过结构体成员地址反推该结构体的地址。

(4)解析

         A、typeof(  ( (type*)0 ) -> member ) )

                  获得 member 成员的数据类型。

         B、const typeof(  ( (type*)0 ) -> member ) )  *_mptr = (ptr)

                  定义常量指针 _mptr,指向 ptr 指向的内容,该指针变量指向的内容是不可变的。

         C、(char *)_mptr - offsetof(type , member)

                  前者将 _mptr 变为 字符指针,后者返回 member 在 type 的偏移量,二者相减就是 type 的首地址了。

           最后在通过  (type *) 转为 type 型地址就可以了。

(5)栗子

#include struct stest
{char    c;int     i;float   f;double  d;
};#define offsetof_t(TYPE , MEMBER) ((size_t)&(((TYPE *)0)->MEMBER))#define container_of_test(ptr , type , member) ({\const typeof(((type *)0)->member) *_mptr = ptr;\(type *)((char *)ptr - offsetof_t(type , member));})int main()
{stest test1;stest *p;p = container_of_test(&test1.i , stest , i);if (p == &test1){std::cout << "二者相同。" << std::endl;}else{std::cout << "二者不同。" << std::endl;}
}

结果:

二者相同

 

 

(SAW:Game Over!)


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部