Linux内核宏offsetof与container_of
offsetof
宏是用来判断结构体中成员的偏移位置,container_of
宏用来根据成员的地址来获取结构体的地址。
offsetof宏
offsetof是返回结构体TYPE中MEMBER成员相对于结构体首地址的偏移量,以字节为单位。
使用offsetof宏需要包含 stddef.h
头文件,实例可以参考:http://www.cplusplus.com/reference/cstddef/offsetof/。
offsetof宏的定义如下: 1
#define offsetof(type, member) (size_t)&(((type*)0)->member)
container_of宏
container_of的主要作用是根据一个结构体变量中的一个域成员变量的指针来获取指向整个结构体变量的指针。
使用container_of宏需要包含 linux/kernel.h
头文件,container_of宏的定义如下所示: 1
2
3#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
第一部分:
const typeof( ((type *)0)->member ) *__mptr = (ptr);
通过 typeof
定义一个 member
指针类型的指针变量 __mptr
,(即__mptr
是指向member
类型的指针),并将__mptr
赋值为ptr
。
第二部分:
(type *)( (char *)__mptr - offsetof(type,member) )
,通过offsetof
宏计算出
member
在 type
中的偏移,然后用
member
的实际地址 __mptr
减去偏移,得到
type
的起始地址,即指向 type
类型的指针。
用一个例子来说明: 1
2
3
4
5
6
7
8
9struct numbers {
int one;
int two;
int three;
} n;
int *ptr = &n.two;
struct numbers *n_ptr;
n_ptr = container_of(ptr, struct numbers, two);
例子
1 | #include <stdio.h> |
运行的结果:
id offset: 0
name offset: 4
age offset: 36
age:10
stu address:0x18c8420
ptr address:0x18c8420