list head結構體的理解

2021-07-10 14:44:19 字數 3180 閱讀 4974

原型:

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...