list.h文件
#ifndef __TONGYISHU_LIST_H #define __TONGYISHU_LIST_H #undef offsetof #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) /** * 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. * */ #undef container_of #define container_of(ptr, type, member) ({ const typeof( ((type *)0)->member ) *__mptr = (ptr); (type *)( (char *)__mptr - offsetof(type,member) );}) struct list_head { struct list_head *next, *prev; }; #undef LIST_HEAD_INIT #define LIST_HEAD_INIT(name) do { (name).prev = &(name); (name).next = &(name); } while (0) /** * list_entry - get the struct for this entry * @ptr: the &struct list_head pointer. * @type: the type of the struct this is embedded in. * @member: the name of the list_struct within the struct. */ #undef list_entry #define list_entry(ptr, type, member) container_of(ptr, type, member) /** * list_for_each_entry - iterate over list of given type * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the list_struct within the struct. */ #undef list_for_each_entry #define list_for_each_entry(pos, head, member) for (pos = list_entry((head)->next, typeof(*pos), member); &pos->member != (head); pos = list_entry(pos->member.next, typeof(*pos), member)) /** * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry * @pos: the type * to use as a loop cursor. * @n: another type * to use as temporary storage * @head: the head for your list. * @member: the name of the list_struct within the struct. */ #undef list_for_each_entry_safe #define list_for_each_entry_safe(pos, n, head, member) for (pos = list_entry((head)->next, typeof(*pos), member), n = list_entry(pos->member.next, typeof(*pos), member); &pos->member != (head); pos = n, n = list_entry(n->member.next, typeof(*n), member)) /** * list_empty - tests whether a list is empty * @head: the list to test. */ static inline int list_empty(const struct list_head *head) { return head->next == head; } /* * Insert a new entry between two known consecutive entries. * * This is only for internal list manipulation where we know * the prev/next entries already! */ static inline void __list_add(struct list_head *_new, struct list_head *prev, struct list_head *next) { next->prev = _new; _new->next = next; _new->prev = prev; prev->next = _new; } /** * list_add_tail - add a new entry * @new: new entry to be added * @head: list head to add it before * * Insert a new entry before the specified head. * This is useful for implementing queues. */ static inline void list_add_tail(struct list_head *_new, struct list_head *head) { __list_add(_new, head->prev, head); } /* * Delete a list entry by making the prev/next entries * point to each other. * * This is only for internal list manipulation where we know * the prev/next entries already! */ static inline void __list_del(struct list_head *prev, struct list_head *next) { next->prev = prev; prev->next = next; } #undef LIST_POISON1 #define LIST_POISON1 ((void *) 0x00100100) #undef LIST_POISON2 #define LIST_POISON2 ((void *) 0x00200200) /** * list_del - deletes entry from list. * @entry: the element to delete from the list. * Note: list_empty() on entry does not return true after this, the entry is * in an undefined state. */ static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = (struct list_head*)LIST_POISON1; entry->prev = (struct list_head*)LIST_POISON2; } #endif
main.c文件
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "list.h" struct Staff { struct list_head list; char id[10]; char name[20]; }; int main() { struct Staff staff_head = { 0 }; struct Staff *pos = NULL, *next = NULL; LIST_HEAD_INIT(staff_head.list); /* list add */ printf("%s", ">>>>>>> list add start. "); for (int i = 0; i < 3; i++) { pos = (struct Staff*)malloc(sizeof(struct Staff)); sprintf(pos->id, "%s%d", "t0051260", i); sprintf(pos->name, "%s%d", "tongyishu-", i); list_add_tail(&pos->list, &staff_head.list); printf("> add list node : "); printf(" id : %s ", pos->id); printf(" name : %s ", pos->name); } printf("%s", ">>>>>>> list add end. "); /* list for each */ printf("%s", ">>>>>>> list for each start. "); list_for_each_entry(pos, &staff_head.list, list) { printf(" id : %s ", pos->id); printf(" name : %s ", pos->name); } printf("%s", ">>>>>>> list for each end. "); /* delete node("t00512601", "tongyishu-1") */ printf("%s", ">>>>>>> delete node start. "); list_for_each_entry_safe(pos, next, &staff_head.list, list) { if (strcmp("t00512601", pos->id) == 0) { list_del(&pos->list); printf("> delete list node : "); printf(" id : %s ", pos->id); printf(" name : %s ", pos->name); free(pos); } } printf("%s", ">>>>>>> delete node end. "); /* list for each again */ printf("%s", ">>>>>>> list for each after delete node start. "); list_for_each_entry(pos, &staff_head.list, list) { printf(" id : %s ", pos->id); printf(" name : %s ", pos->name); } printf("%s", ">>>>>>> list for each after delete node end. "); /* release resource */ printf("%s", ">>>>>>> release resource start. "); list_for_each_entry_safe(pos, next, &staff_head.list, list) { list_del(&pos->list); free(pos); } printf("%s", ">>>>>>> release resource end. "); return 0; }
输出结果:
>>>>>>> list add start. > add list node : id : t00512600 name : tongyishu-0 > add list node : id : t00512601 name : tongyishu-1 > add list node : id : t00512602 name : tongyishu-2 >>>>>>> list add end. >>>>>>> list for each start. id : t00512600 name : tongyishu-0 id : t00512601 name : tongyishu-1 id : t00512602 name : tongyishu-2 >>>>>>> list for each end. >>>>>>> delete node start. > delete list node : id : t00512601 name : tongyishu-1 >>>>>>> delete node end. >>>>>>> list for each after delete node start. id : t00512600 name : tongyishu-0 id : t00512602 name : tongyishu-2 >>>>>>> list for each after delete node end. >>>>>>> release resource start. >>>>>>> release resource end.