原型:
struct ******x
;
結構圖如下所示
特點是單向只能從前往後查詢,橙色線代表單向迴圈煉表相較於單向鍊錶所多出來的線
原型:
struct bothlist
特點是雙向,從前往後,從後往前都可以查詢,橙色線是雙向迴圈煉表相較雙向鍊錶所多出來的兩條線
原型:
struct list_head ;
此結構體所構成的鍊錶如上面的雙向迴圈鍊錶圖示
此結構體在linux核心中被大量的引用,幾乎所有核心當中需要構成鍊錶結構的地方都用到了這個結構體。例如核心的匯流排裝置就用到了這個結構體
例如現在有任意給定的乙個結構體需要組成乙個雙向鍊錶,則可以在此結構體當中加入list_head結構體用來進行鍊錶的構建,例如結構體原型如下
struct test_list
;
下面是根據此結構體以及list_head檔案中的函式編寫的測試檔案,使用gcc4.8.1進行編譯
#include //#include "list.h"
struct list_head ;
struct test_list
;static struct test_list lists = ,
[1] = ,
[2] = ,
[3] = ,
[4] =
};struct list_head head = ;
static void __list_add_tail(struct list_head *new, struct list_head *prev, struct list_head *next)
void mlist_add_tail(struct list_head *new, struct list_head *head)
#define mlist_entry(list_head, type, member_name) \
(type *)((unsigned int)list_head - (unsigned int)(&(((type*)(0))->member_name)))
#define mlist_for_each(pos, head) \
for(pos = (head)->prev; pos != head; pos = pos->prev)
int main(int argv, char *argc)
getchar();
return 0;
}
上述**經過編譯之後執行的結果如下
4 (null)
3 test
2 (null)
1 (null)
0 hehe
後經修改
#define mlist_for_each(pos, head) \
for(pos = (head)->prev; pos != head; pos = pos->prev)
為
#define mlist_for_each(pos, head) \
for(pos = (head)->next; pos != head; pos = pos->next)
執行結果如下
0 hehe
1 (null)
2 (null)
3 test
4 (null)
由此可以得知此鍊錶的結構為乙個雙向鍊錶。
首先是頭結點的建立以及初始化
struct list_head head = ;
此時head的結構體成員均指向自己,形如
鍊錶的新增過程
由結構體內部的list_head結構體得到結構體所在的位置
#define mlist_entry(list_head, type, member_name) \
(type *)((unsigned int)list_head - (unsigned int)(&(((type*)(0))->member_name)))
反映到**
mlist_entry(mod, struct test_list, test)得到
(struct test_list *)((unsigned int)mod - (unsigned int)(&((( struct test_list *)(0))-> test)))
分層次解析
((( struct test_list *)(0))-> test)
定義乙個test_list結構體變數0,使其指向其中的test成員。
(&((( struct test_list *)(0))-> test)))
取此成員所在的位址,由於起始為0位址,所以現在獲得的位址就是test_list結構體開始到其test成員的偏移值,將其強制轉換為unsigned int型變數
((unsigned int)mod - (unsigned int)(&((( struct test_list *)(0))-> test)))
拿取得的list_head結構體mod的位置減去偏移值得到當前mod所在的test_list結構體的起始位置,最後將這個值強制轉換為test_list結構體指標,之後就得到乙個test_list的位址,也就是當前list_head結構體所在的那個test_list。
其餘諸如鍊錶的刪除等等操作相對容易理解,不再贅述
結構體指標的應用理解
在cjson呼叫時遇到的結構體引數賦值時的問題,需要cjson 才行,下面兩種方法都行,對比一下。也對指標理解更深入 結構體給函式當形參時,由於主函式裡也沒分配結構體空間,只有結構體的位址,區域性函式裡面只能給區域性結構體位址,給結構體的位址放在結構體位址的空間中,要有存放結構體位址空間的位址,也就...
結構體大小sizeof的理解
在32位編譯環境中 sizeof的用法 sizeof char 1 sizeof int 4 sizeof unsigned int 4 sizeof long int 4 sizeof short int 2 sizeof float 4 sizeof double 8 2.指標變數的sizeof...
libevent幾個結構體的理解
struct event base struct event base 這裡要注意struct event list activequeues 為什麼用雙指標,這是因為很多事件的優先順序一致,所以用佇列陣列來存放,這樣導致有些事件不能第一時間處理 struct event 這裡主要理解幾個 tail...