且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

linux中链表的使用【转】

更新时间:2022-08-22 11:12:40

转自:http://blog.csdn.net/finewind/article/details/8074990

linux中链表的使用【转】
 Linux下链表的使用方法跟我们常规的不一样,通常情况下,链表的next指针都指向节点的起始位置,但linux中链表指向的是下一个节点中链表所在的地址,这是一种很好的处理方法,不用每换一种数据结构就处理,这种方法的难点在于从链表地址中推算出原始结构体的地址。

   整理后的代码如下:

list.h

[cpp] view plain copy

    #ifndef _LIST_H_  
    #define _LIST_H_  
      
    /********************************************************** 
    功能: 计算MEMBER成员在TYPE结构体中的偏移量 
    **********************************************************/  
    #define offsetof(TYPE, MEMBER)  (unsigned long)(&(((TYPE*)0)->MEMBER))  
      
      
    /********************************************************** 
    功能: 计算链表元素的起始地址 
    输入:  
        ptr:    type结构体中的链表指针 
        type:   结构体类型 
        member: 链表成员名称 
    **********************************************************/  
    #define container_of(ptr, type, member) (type *)((char*)(ptr) - offsetof(type, member))  
      
    #define LIST_HEAD_INIT(name)    {&(name), &(name)}  
      
    struct list  
    {  
        struct list *prev, *next;  
    };  
      
    static inline void list_init(struct list *list)  
    {  
        list->next = list;  
        list->prev = list;  
    }  
      
    static inline int list_empty(struct list *list)  
    {  
        return list->next == list;  
    }  
      
    // 将new_link插入到link之前  
    static inline void list_insert(struct list *link, struct list *new_link)  
    {  
        new_link->prev        = link->prev;  
        new_link->next        = link;  
        new_link->prev->next = new_link;  
        new_link->next->prev = new_link;  
    }  
      
    /********************************************************** 
    功能: 将new_link节点附加到list链表中 
    **********************************************************/  
    static inline void list_append(struct list *list, struct list *new_link)  
    {  
        list_insert(list, new_link);  
    }  
      
    /********************************************************** 
        功能: 从链表中移除节点 
    **********************************************************/  
    static inline void list_remove(struct list *link)  
    {  
        link->prev->next = link->next;  
        link->next->prev = link->prev;  
    }  
      
    /********************************************************** 
    获取link节点对应的结构体变量地址 
    link:   链表节点指针 
    type:   结构体类型名 
    member: 结构体成员变量名 
    **********************************************************/  
    #define list_entry(link, type, member)  container_of(link, type, member)  
      
      
    /********************************************************** 
    获取链表头节点对应的结构体变量地址 
    list:   链表头指针 
    type:   结构体类型名 
    member: 结构体成员变量名 
    Note: 
    链表头节点实际为链表头的下一个节点,链表头未使用,相当于哨兵 
    **********************************************************/  
    #define list_head(list, type, member) list_entry((list)->next, type, member)  
      
    /********************************************************** 
    获取链表尾节点对应的结构体变量地址 
    list:   链表头指针 
    type:   结构体类型名 
    member: 结构体成员变量名 
    **********************************************************/  
    #define list_tail(list, type, member) list_entry((list)->prev, type, member)  
      
    /********************************************************** 
    返回链表下一个节点对应的结构体指针 
    elm:    结构体变量指针 
    type:   结构体类型名 
    member: 结构体成员变量名(链表变量名) 
    **********************************************************/  
    #define list_next(elm,type,member) list_entry((elm)->member.next, type, member)  
      
    /********************************************************** 
    遍历链表所有节点对应的结构体 
    pos : 结构体指针 
    type : 结构体类型名 
    list : 链表头指针 
    member : 结构体成员变量名(链表变量名) 
    Note : 链表头未使用,因此遍历结束后,pos指向的不是有效的结构体地址 
    **********************************************************/  
    #define list_for_each_entry(pos, type, list, member)    \  
    for (pos = list_head(list, type, member);               \  
        &pos->member != (list);                              \  
        pos = list_next(pos, type, member))  
      
      
    /********************************************************** 
    example function 
    **********************************************************/  
    void list_example(void);  
    #endif  

测试代码:

list.cpp
[cpp] view plain copy

    #include "stdafx.h"  
      
      
    #include "list.h"  
    #include <stdlib.h>  
      
    struct list g_list = LIST_HEAD_INIT(g_list);  
      
    struct test  
    {  
        int a;  
        int b;  
        char c;  
        struct list link;  
    };  
      
    void CreateData(int a, int b, char c)  
    {  
        struct test *pdata = (struct test *)malloc(sizeof(struct test));  
        pdata->a = a;  
        pdata->b = b;  
        pdata->c = c;  
        list_append(&g_list, &(pdata->link));  
    }  
      
    void listTest(void)  
    {  
        // 创建节点  
        CreateData(0,0,0);     
        CreateData(10,11,12);  
        CreateData(20,21,22);  
        CreateData(30,31,32);  
        CreateData(40,41,42);  
          
        // 取节点  
        struct list *templist = &g_list;   
        struct test *pdata;  
        pdata = list_entry(templist->next, struct test, link);   
      
        templist = templist->next;  
        pdata = list_entry(templist->next, struct test, link);  
      
        // 遍历1  
        for (templist = g_list.next; templist != &g_list; templist = templist->next)  
            pdata = list_entry(templist, struct test, link);  
      
        // 遍历2  
        //pdata = list_head(&g_list, struct test, link);  
        for (pdata = list_head(&g_list, struct test, link); &(pdata->link) != &g_list; pdata = list_next(pdata, struct test, link))  
        {  
            pdata->a = 1;  
        }  
      
        // 遍历3  
        list_for_each_entry(pdata, struct test, &g_list, link)  
        {  
            pdata->b = 2;      
        }  
          
      
    }  
linux中链表的使用【转】

 





本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/7130941.html,如需转载请自行联系原作者