转自:http://blog.csdn.net/finewind/article/details/8074990
Linux下链表的使用方法跟我们常规的不一样,通常情况下,链表的next指针都指向节点的起始位置,但linux中链表指向的是下一个节点中链表所在的地址,这是一种很好的处理方法,不用每换一种数据结构就处理,这种方法的难点在于从链表地址中推算出原始结构体的地址。 整理后的代码如下: list.h [cpp] view plain copy #ifndef _LIST_H_ #define _LIST_H_ /********************************************************** 功能: 计算MEMBER成员在TYPE结构体中的偏移量 **********************************************************/ #define offsetof(TYPE, MEMBER) (unsigned long)(&(((TYPE*)0)->MEMBER)) /********************************************************** 功能: 计算链表元素的起始地址 输入: ptr: type结构体中的链表指针 type: 结构体类型 member: 链表成员名称 **********************************************************/ #define container_of(ptr, type, member) (type *)((char*)(ptr) - offsetof(type, member)) #define LIST_HEAD_INIT(name) {&(name), &(name)} struct list { struct list *prev, *next; }; static inline void list_init(struct list *list) { list->next = list; list->prev = list; } static inline int list_empty(struct list *list) { return list->next == list; } // 将new_link插入到link之前 static inline void list_insert(struct list *link, struct list *new_link) { new_link->prev = link->prev; new_link->next = link; new_link->prev->next = new_link; new_link->next->prev = new_link; } /********************************************************** 功能: 将new_link节点附加到list链表中 **********************************************************/ static inline void list_append(struct list *list, struct list *new_link) { list_insert(list, new_link); } /********************************************************** 功能: 从链表中移除节点 **********************************************************/ static inline void list_remove(struct list *link) { link->prev->next = link->next; link->next->prev = link->prev; } /********************************************************** 获取link节点对应的结构体变量地址 link: 链表节点指针 type: 结构体类型名 member: 结构体成员变量名 **********************************************************/ #define list_entry(link, type, member) container_of(link, type, member) /********************************************************** 获取链表头节点对应的结构体变量地址 list: 链表头指针 type: 结构体类型名 member: 结构体成员变量名 Note: 链表头节点实际为链表头的下一个节点,链表头未使用,相当于哨兵 **********************************************************/ #define list_head(list, type, member) list_entry((list)->next, type, member) /********************************************************** 获取链表尾节点对应的结构体变量地址 list: 链表头指针 type: 结构体类型名 member: 结构体成员变量名 **********************************************************/ #define list_tail(list, type, member) list_entry((list)->prev, type, member) /********************************************************** 返回链表下一个节点对应的结构体指针 elm: 结构体变量指针 type: 结构体类型名 member: 结构体成员变量名(链表变量名) **********************************************************/ #define list_next(elm,type,member) list_entry((elm)->member.next, type, member) /********************************************************** 遍历链表所有节点对应的结构体 pos : 结构体指针 type : 结构体类型名 list : 链表头指针 member : 结构体成员变量名(链表变量名) Note : 链表头未使用,因此遍历结束后,pos指向的不是有效的结构体地址 **********************************************************/ #define list_for_each_entry(pos, type, list, member) \ for (pos = list_head(list, type, member); \ &pos->member != (list); \ pos = list_next(pos, type, member)) /********************************************************** example function **********************************************************/ void list_example(void); #endif 测试代码: list.cpp [cpp] view plain copy #include "stdafx.h" #include "list.h" #include <stdlib.h> struct list g_list = LIST_HEAD_INIT(g_list); struct test { int a; int b; char c; struct list link; }; void CreateData(int a, int b, char c) { struct test *pdata = (struct test *)malloc(sizeof(struct test)); pdata->a = a; pdata->b = b; pdata->c = c; list_append(&g_list, &(pdata->link)); } void listTest(void) { // 创建节点 CreateData(0,0,0); CreateData(10,11,12); CreateData(20,21,22); CreateData(30,31,32); CreateData(40,41,42); // 取节点 struct list *templist = &g_list; struct test *pdata; pdata = list_entry(templist->next, struct test, link); templist = templist->next; pdata = list_entry(templist->next, struct test, link); // 遍历1 for (templist = g_list.next; templist != &g_list; templist = templist->next) pdata = list_entry(templist, struct test, link); // 遍历2 //pdata = list_head(&g_list, struct test, link); for (pdata = list_head(&g_list, struct test, link); &(pdata->link) != &g_list; pdata = list_next(pdata, struct test, link)) { pdata->a = 1; } // 遍历3 list_for_each_entry(pdata, struct test, &g_list, link) { pdata->b = 2; } }