@time 2019-07-10
@author Ruo_Xiao
@revision linux 2.6.11
1、 offsetof
(1)原型
/*
* @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 <iostream>
#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;
}
结果:
stest::c 的偏移量:0
stest::i 的偏移量:4
stest::f 的偏移量:8
stest::d 的偏移量:16
2、container_of
(1)原型
/*
* @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 <iostream>
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!)