LIST_ENTRY
链表的定义:
typedef struct _LIST_ENTRY |
LIST_ENTRY表示一个链表的节点,其中Flink成员指向当前节点的后一个节点,Blink成员指向当前节点的前一个节点。
链表的使用:
typedef struct _TestListEntry |
m_ulDataA成员处于最低地址,m_ulDataD处于最高地址,而链表节点LIST_ENTRY的两个成员展开后在结构体中分别为Flink与Blink,其中Flink处于低地址,Blink处于高地址。
头结点初始化
头结点的定义和初始化
LIST_ENTRAY ListHeader = {0}; |
InitializeListHead函数,函数只有一个参数ListHead,表示需要被初始化的头节点
VOID InitializeListHead(_Out_PLIST_ENTRAY ListHead) |
当只存在头结点的时候,没有其他节点时,这个链表就是一个空链表,用 IsListEmpty 可以判断一个链表是否为空,IsListEmpty返回TRUE表示链表为空链表,返回FALSE表示链表非空。
BOOLEAN IslistEmpty(const_LIST_ENTRY *ListHead ); |
节点插入
InsertHeadList函数的作用是把一个节点插入到链表的第一个位置
InsertTailList函数的作用是把一个节点插入到链表的最后一个位置
VOID InsertHeadList(PLIST_ENTRY ListHead, PLSIT_ENTRY Entry); |
链表的遍历
链表遍历可以通过Flink指针从前往后遍历,也可以通过Blink从后往前遍历。
PLIST_ENTRY pListEntry = NULL; |
pTestEntry指针的获取:
在while循环块中,是通过pListEntry指针进行遍历的,而pListEntry指向的地址是TestListEntry结构体中的m_ListEntry地址,而m_ListEntry成员的地址并不是这个结构体的首地址,所以这里需要通过一个宏CONTAINING_RECORD把m_ListEntry的地址转换成结构体TestListEntry的首地址.
CONTAINING_RECORD宏的用法:
PCHAR CONTAINING_RECORD(PCHAR Address,TYPE Type,PCHAR Field); |
Address表示LIST_ENTRY的地址,在本例中,就是pListEntry指向的地址
Type表示类型,在本例中为TestListEntry
Field表示结构体中LIST_ENTRY成员的名字,在本例中为m_ListEntry。
CONTAINING_RECORD宏通过Type与Field这两个成员,计算出Field成员距离结构体顶部的内存距离,然后结合具体的Address成员,算出最终的结构体首地址。
节点移除
-
移除链表中第一个节点与最后一个节点分别使用RemoveHeadList以及RemoveTailList函数。
PLIST_ENTRY RemoveHeadList(PLIST_ENTRY ListHead);
PLIST_ENTRY RemoveTailList(PLIST_ENTRY ListHead);函数仅有一个参数,表示所需要移除的链表头节点指针,这两个函数的返回值均为PLIST_ENTRY,成功移除则返回从链表移除的节点指针,如果无节点可以移除(如链表为空)则返回NULL。
-
移除某个特定节点,即可使用RemoveEntryList函数。
BOOLEAN RemoveEntryList(PLSIT_ENTRY Entry);
Entry表示需要移除的链表节点指针,RemoveEntryList函数的返回值类型为BOOLEAN,节点被移除后,若链表变为空链表,RemoveEntryList返回TRUE,否则返回FALSE。