1、#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
先分析一下这个 宏的运行机理:
一共4步
1. ( (TYPE *)0 ) 将零转型为TYPE类型指针;
2. ((TYPE *)0)->MEMBER 访问结构中的数据成员;
3. &( ( (TYPE *)0 )->MEMBER )取出数据成员的地址; 这个实现相当于获取到了 MEMBER 成员相对于其所在结构体的偏移,也就是其在对应结构体中的什么位置。
4.(size_t)(&(((TYPE*)0)->MEMBER))结果转换类型。巧妙之处在于将0转 换成(TYPE*),结构以内存空间首地址0作为起始地址,则成员地址自然为偏移地址;
&a->member,会把访问a->member的操作取消,只会计算出a->member的地址。
例如
struct node
{
int a;
char b;
int c;
};
int offset=offsetof(struct node,c);
结果为8,正确。
offsetof作用就是在已知某一个成员变量的名字和结构体类型的情况下,计算该成员相对于结构体的起始地址的偏移量。
2、container_of
#ifndef container_of
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
关于typeof,这是gcc的C语言扩展保留字,用于声明变量类型.
const typeof( ((type *)0->member ) *__mptr = (ptr);意思是声明一个与member同一个类型的指针常量 *__mptr,并初始化为ptr.
(type *)( (char *)__mptr - offsetof(type,member) );意思是__mptr的地址减去member在该struct中的偏移量,两者相减得到结构体的起始位置, 再强制转换成 type 类型。
container_of 的作用就是在已知某一个成员变量的名字、指针和结构体类型的情况下,计算结构体的指针,也就是计算结构体的起始地址。
3、LIST_HEAD
#define LIST_HEAD_INIT(name) { &(name), &(name); }
#define LIST_HEAD(name) (\
struct list_head name = LIST_HEAD_INIT(name);)
struct list_head {
struct list_head *next, *prev;
};
使用方法
一、struct list_head head; LIST_HEAD_INIT(head); 二、 LIST_HEAD(head;