libubox/list.h 将数据与指针分隔开,这样就不关心业务数据
struct list_head
{
struct list_head *prev;
struct list_head *next;
};
struct list_head head;
struct data
{
int num;
char name[10];
struct list_head node;
};
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
分析:/*
* (a) ((struct data *)0) 将地址0强制转化成struct data指针类型
* (b) ((struct data *)0)->node 访问结构体中的node成员
* (c) &(((struct data *)0)->node) 获取成员node的地址,表示node成员在结构体中的偏移量
* (d) ((size_t) &((struct data *)0)->node)) size_t在32位系统中表示unsigned int,在64位系统中表示unsigned long
*
*/
#define container_of(ptr, type, member)({ \
const typeof( ((type *)0)->member) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type, member));})
/*
* (a) typeof( ((struct data *)0)->node ) 获取成员node的数据类型, struct list_head
* (b) const ( ((struct data *)0)->node ) *__mptr = &(data->node)
* const struct list_head *__mptr = &(data->node)
* (c) offsetof(struct data, node) 获取结构体中node成员的偏移量
* (d) ((char *)__mptr - offsetof(struct data, node) 获取到结构体的起使位置,地址转char * 计算,下面使用再转结构体指针类型
* (e) (struct data *) ((char *)__mptr - offsetof(struct data, node)
*/
使用宏:
INIT_LIST_HEAD(&head);
struct list_head *phead = NULL;
struct data *mydata = NULL;
list_for_each(phead , &head)
{
mydata = container_of(phead, struct data, node);
printf("num = %d name = %s\n", mydata->num, mydata->name);
}