1. 程式人生 > >contiki之list標頭檔案

contiki之list標頭檔案

contiki裡有很多基礎的資料結構和對應的操作函式,比如說記憶體管理memb,列表list 佇列queuebuff等等。如果不把這些最基礎的東西啃下的話,你去看上層的協議比如說ipv6 ,rpl等,那是寸步難行,根本不知道在幹嘛。接下來打算把這些資料結構挨個過一遍。接下來翻list的原始碼吧。 /***************************list.h**********************************/ #define LIST_CONCAT2(s1, s2) s1##s2 #define LIST_CONCAT(s1, s2) LIST_CONCAT2(s1, s2) 這兩個巨集就是用來拼接的,待會就會看到怎麼用。 #define LIST(name) \ static void *LIST_CONCAT(name,_list) = NULL; \ static list_t name = (list_t)&LIST_CONCAT(name,_list) 這個巨集用來定義兩個跟連結串列有關的指標,用一開始LIST_CONCAT巨集展開的話就是 static void* name_list = NULL static list_t name = (list_t)&name_list 這個list_t又是啥,追蹤下去發現是 typedef void ** list_t;
也就是說定義了一個指標叫name_list,還有一個指向指標的指標name #define LIST_STRUCT(name) \ void *LIST_CONCAT(name,_list); \ list_t name 這巨集定義跟上面的很像,關鍵就是少了個static,看註釋上也是說上面的巨集定義的是模組內部使用的靜態變數,這個巨集定義的是全域性。其實還不僅如此,我搜了一下用到這個巨集的地方,在uip-ds6-route.h裡有,如下 struct uip_ds6_route_neighbor_routes { LIST_STRUCT(route_list); }; 而LIST這個巨集在nbr_table.c裡是這樣的 LIST(nbr_table_keys); 也就是說用LIST的時候定義的是兩個零散的變數,用LIST_STRUCT的時候變數是被裝在一個結構體裡的。好,接著往下看。 #define LIST_STRUCT_INIT(struct_ptr, name) \
do { \ (struct_ptr)->name = &((struct_ptr)->LIST_CONCAT(name,_list)); \ (struct_ptr)->LIST_CONCAT(name,_list) = NULL; \ list_init((struct_ptr)->name); \ } while(0) 這個巨集呢就是用來給 LIST_STRUCT巨集定義的結構體初始化用的。這樣看可能不是很清楚這個巨集的原理,結合例項看就明白了。在uip-ds6-route.c裡有如下語句 struct uip_ds6_route_neighbor_routes *routes;
LIST_STRUCT_INIT(routes, route_list); uip_ds6_route_neighbor_routes就是包含了 LIST_STRUCT的結構體型別。 list_init((struct_ptr)->name)這句感覺是多餘的,跟 (struct_ptr)->LIST_CONCAT(name,_list) = NULL是一樣的。 接下來老規矩,就是一堆針對這個list資料結構的操作函式聲明瞭。 void list_init(list_t list); void * list_head(list_t list); void * list_tail(list_t list); void * list_pop (list_t list); void list_push(list_t list, void *item);
void * list_chop(list_t list);
void list_add(list_t list, void *item); void list_remove(list_t list, void *item);
int list_length(list_t list);
void list_copy(list_t dest, list_t src);
void list_insert(list_t list, void *previtem, void *newitem);
void * list_item_next(void *item);
#endif /* LIST_H_ */ 你可能覺得怪怪的,這個list結構體有點空蕩蕩的,就一個指標還有一個指向這個指標的指標,就兩個變數而已,算什麼列表?別急,看了list.c就會明白,這個list的適用面很廣,設計得很靈活。