1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
| /** 双向链表示例。演示创建、遍历、删除等操作。 g++ 5.8.4 & VS2010 测试通过 Late Lee <latelee@163.com> http://www.latelee.org 由hostapd的list源码修改而成 结构示意图: list_head prev ----------------------------------------------- | | -<- | next | node1 node2 node3 | ^| | | || | data... data... data... | || --- prev <--------- prev <--------- prev <-----| ||-----> next ---------> next ---------> next ------ | data... data... data... | |-----<---------------------------------------------- 头结点不使用,无法用list_entry拿到实际数据 list_head的prev指向最后一个结点,next指向第一个结点。 如果一直用next可遍历并循环到开始处,prev亦然。 注:list_add本身在“结点”后添加,如在list_haed“后”添加,则变成在整个链表开头。 如果在node1“后”添加,则在整个链表的node1后新加结点。 运行结果: show info in the list. [0] busnum: 10, slave: 0 [1] busnum: 11, slave: 2 [2] busnum: 12, slave: 4 [3] busnum: 13, slave: 6 [4] busnum: 14, slave: 8 prev entry: 14 next entry: 10 first entry: 10 last entry: 14 show info in the list. [0] busnum: 1, slave: 25 [1] busnum: 10, slave: 0 [2] busnum: 250, slave: 25 [3] busnum: 11, slave: 2 [4] busnum: 250, slave: 25 [5] busnum: 12, slave: 4 [6] busnum: 14, slave: 8 [7] busnum: 65535, slave: 25 after delete... list empty, nothing to show. next1 entry: 1 next2 entry: 2 next3 entry: 0(0x0) next4 entry: 1 next5 entry: 2 */ #include <stdio.h> #include <stdlib.h> #include "list.h" struct i2c_devinfo { struct list_head list; int busnum; int slave; }; // 定义链表 LIST_HEAD(my_list); void init(int busnum, int slave) { struct i2c_devinfo* devinfo; // 分配空间 devinfo = (struct i2c_devinfo*)malloc(sizeof(struct i2c_devinfo)); if (devinfo == NULL) return; // 赋值 devinfo->busnum = busnum; devinfo->slave = slave; // 添加到链接中 list_add_tail(&devinfo->list, &my_list); } void show(void) { struct i2c_devinfo *devinfo; int i = 0; if (list_empty(&my_list)) { printf("list empty, nothing to show.\n"); return; } printf("show info in the list.\n"); // 解释:从全局链表my_list中拿到devinfo信息,其中list为devinfo类型的一个成员变量 //list_for_each(devinfo, &my_list, struct i2c_devinfo, list) list_for_each(devinfo, &my_list, struct i2c_devinfo, list) { printf("[%d] busnum: %d, slave: %d\n", i++, devinfo->busnum, devinfo->slave); } } void delete_list(void) { struct i2c_devinfo *devinfo, *tdev; // 注:当要删除链表数据时,要使用*_safe,同时要额外增加一个临时变量 list_for_each_safe(devinfo, tdev, &my_list, struct i2c_devinfo, list) { list_del(&devinfo->list); free(devinfo); } } void list_misc(void) { struct i2c_devinfo* devinfo, *tdev, *tmpdev; struct i2c_devinfo* n; n = list_entry(my_list.prev, struct i2c_devinfo, list); printf("prev entry: %d\n", n->busnum); n = list_entry(my_list.next, struct i2c_devinfo, list); printf("next entry: %d\n", n->busnum); // 获取第一个、最后一个 n = list_first_entry(&my_list, struct i2c_devinfo, list); printf("first entry: %d\n", n->busnum); n = list_last_entry(&my_list, struct i2c_devinfo, list); printf("last entry: %d\n", n->busnum); // devinfo = (struct i2c_devinfo*)malloc(sizeof(struct i2c_devinfo)); devinfo->busnum = 1; devinfo->slave = 25; list_add(&devinfo->list, &my_list); // 在my_list后添加,变成在链表的头部 // note1 devinfo = (struct i2c_devinfo*)malloc(sizeof(struct i2c_devinfo)); devinfo->busnum = 65535; devinfo->slave = 25; list_add_tail(&devinfo->list, &my_list); // 在末尾 // 中途插入、删除 //list_for_each(tdev, &my_list, struct i2c_devinfo, list) list_for_each_safe(tdev, tmpdev, &my_list, struct i2c_devinfo, list) { if (tdev->busnum == 10) // 在此节点后插入 { devinfo = (struct i2c_devinfo*)malloc(sizeof(struct i2c_devinfo)); devinfo->busnum = 250; devinfo->slave = 25; list_add(&devinfo->list, &tdev->list); // note2 } if (tdev->busnum == 12) // 在此节点前插入 { devinfo = (struct i2c_devinfo*)malloc(sizeof(struct i2c_devinfo)); devinfo->busnum = 250; devinfo->slave = 25; list_add_prev(&devinfo->list, &tdev->list); } if (tdev->busnum == 13) // 删除此节点 { list_del(&tdev->list); } } } // 遍历示例 void list_misc1(void) { LIST_HEAD(my_list); struct i2c_devinfo* devinfo; devinfo = (struct i2c_devinfo*)malloc(sizeof(struct i2c_devinfo)); devinfo->busnum = 1; devinfo->slave = 25; list_add_tail(&devinfo->list, &my_list); devinfo = (struct i2c_devinfo*)malloc(sizeof(struct i2c_devinfo)); devinfo->busnum = 2; devinfo->slave = 25; list_add_tail(&devinfo->list, &my_list); struct i2c_devinfo* n; n = list_entry(my_list.next, struct i2c_devinfo, list); // 第一个结点 printf("next1 entry: %d\n", n->busnum); n = list_entry(my_list.next->next, struct i2c_devinfo, list); // 第二个结点 printf("next2 entry: %d\n", n->busnum); n = list_entry(my_list.next->next->next, struct i2c_devinfo, list); // 回到my_list,此时数据无效 printf("next3 entry: %d(0x%x)\n", n->busnum, n->busnum); n = list_entry(my_list.next->next->next->next, struct i2c_devinfo, list); // 第一个结点 printf("next4 entry: %d\n", n->busnum); n = list_entry(my_list.next->next->next->next->next, struct i2c_devinfo, list); // 第二个结点 printf("next5 entry: %d\n", n->busnum); } int main(void) { int i = 0; int j = 0; for (i = 10; i < 15; i++, j += 2) { init(i, j); } show(); list_misc(); show(); printf("after delete...\n"); delete_list(); // 删除链表后,已经没有内容了 show(); list_misc1(); return 0; }
|