list_head(list_for_each_entry)
エレメントの要素のstruct list_head listから取得したアドレスはエレメントのアドレスでなく、エレメント要素のstruct list_head listのアドレスで、struct list_head listが先頭要素ならstruct list_head listのアドレスは、エレメントアドレスとなりますが、そうでないなら、struct list_head listのオフセット位置を差し引いたアドレスのエレメントアドレスとする実装となります。
[root@localhost c]# ./a.out
#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)) #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) #define list_entry(ptr, type, member) \ container_of(ptr, type, member)[root@localhost c]# cat list_head2.c
#include <stdio.h> #include <stddef.h> void get_list(char* msg); void add_tail_list(int id); void add_head_list(int id); void init_link_list(); struct list_head { struct list_head *next, *prev; }; struct babakaka { char id1; char name[2]; struct list_head list; char id2; }; struct list_head head; struct babakaka element[10]; void init_element() { int i; head.next = &head; head.prev = &head; for(i = 0; i < 10; i++) { element[i].id1 = i; element[i].id2 = i + 10; sprintf(element[i].name, "%c", 'a'+i); element[i].name[1] = 0; } } void main() { init_element(); init_link_list(); get_list("init"); add_tail_list(4); add_tail_list(5); add_tail_list(6); get_list("add tail"); add_head_list(7); add_head_list(8); add_head_list(9); get_list("add head"); } void init_link_list() { int i; head.next = &element[0].list; element[0].list.prev = &head; element[0].list.next = &element[1].list; element[1].list.prev = &element[0].list; element[1].list.next = &element[2].list; element[2].list.prev = &element[1].list; element[2].list.next = &element[3].list; element[3].list.prev = &element[2].list; element[3].list.next = &head; head.prev = &element[3].list; } void add_head_list(int id) { struct list_head *a, *b, *c; a = &head; b = &element[id].list; c = head.next; a->next = b; b->prev = a; b->next = c; c->prev = b; } void add_tail_list(int id) { struct list_head *a, *b, *c; a = &head; b = &element[id].list; c = head.prev; a->prev = b; b->next = a; b->prev = c; c->next = b; } void get_list(char* msg) { struct babakaka *p; int listoffset_of_babakaka; printf("%10s:", msg); listoffset_of_babakaka = offsetof(struct babakaka, list); for (p = (struct babakaka *) ((char *)head.next - listoffset_of_babakaka); p->list.next != &head; p = (struct babakaka *)((char *)p->list.next - listoffset_of_babakaka)) { printf("[%d.%s.%d] ", p->id1, p->name, p->id2); } printf("\n"); }
[root@localhost c]# ./a.out
init:[0.a.10] [1.b.11] [2.c.12] add tail:[0.a.10] [1.b.11] [2.c.12] [3.d.13] [4.e.14] [5.f.15] add head:[9.j.19] [8.i.18] [7.h.17] [0.a.10] [1.b.11] [2.c.12] [3.d.13] [4.e.14] [5.f.15]