內核鏈表:
特點:節點的指針域指向下一個節點/上一個節點的指針域,由此可以統一指針的類型,具有一般通用性,使用指針域跟數據入口地址【設爲0地址】的offset來尋找數據入口,從而輸出節點數據;內核鏈表一般爲雙向循環鏈表。
C++實現內核鏈表功能的例子,由此此處是參考C語言編寫而成的,其中形參所用的爲指針形參而不是引用,後期有時間再來修改
/*******************************************************************
Author: OJ_GDUT
Function: imitate the linked list of kernel
Date: 2016-03-27
********************************************************************/
#include <iostream>
#include <typeinfo>
using namespace std;
/*
* define the pointer field
*/
struct list_head{
list_head *prev;
list_head *next;
};
list_head head_list; //define the linked list head,此處不能聲明爲指針,因爲如果聲明爲指針則並沒有爲struct list_head分配棧空間
/*
* test parameters
*/
#if 1
class score{
friend int main(void);
private:
int num;
int english;
int math;
public:
list_head list;
}stu1, stu2, stu3;
#else
struct score{
int num;
int english;
int math;
list_head list;
}stu1, stu2, stu3;
#endif
list_head *pos; //define the loop cursor,此處可以聲明爲指針,因爲之後會對其進行替換
score *tmp; //define the a pointer that points to score,此處可以聲明爲指針,因爲之後會對其進行替換
/*****************************************************
Function name: INIT_LIST_HEAD
Function: init the linked list head
Parameters:
struct list_head *list:the list_head that will be init
*******************************************************/
static inline void INIT_LIST_HEAD(list_head *list)
{
list->next = list;
list->prev = list; //如果不對head_list進行初始化,此處的list->next/prev會無定義,從而出現訪問衝突
}
/*****************************************************
Function name: list_add_tail
Function: add the list from the tail
Parameters:
list_head *l_new: the new node
list_head *head: the list head
*******************************************************/
void list_add_tail(list_head *l_new, list_head *head)
{
list_head *prev = head->prev;
list_head *next = head;
prev->next = l_new;
next->prev = l_new;
l_new->prev = prev;
l_new->next = next;
}
/*****************************************************
Function name: list_for_each
Function: add the list from the tail
Parameters:
list_head *pos: the &struct list_head to use as a loop cursor
list_head *head: the head for your list
*******************************************************/
#define list_for_each(pos, head) for(pos = head->next; pos != head; pos = pos->next)
/*****************************************************
Function name: list_del
Function: deletes entry from list
Parameters:
list_head *entry:the element to delete from the list
*******************************************************/
static inline void list_del(list_head *entry)
{
list_head *prev = entry->prev;
list_head *next = entry->next;
next->prev = prev;
prev->next = next;
entry->prev = nullptr;
entry->next = nullptr;
}
/*****************************************************
Function name: main
Function: test the linked_list
Parameters: void
*******************************************************/
int main(void)
{
/*1.初始化表頭*/
INIT_LIST_HEAD(&head_list);
/*2.定義節點並插入節點*/
stu1.num = 1;
stu1.english = 91;
stu1.math = 81;
list_add_tail(&(stu1.list), &head_list);
stu2.num = 2;
stu2.english = 92;
stu2.math = 82;
list_add_tail(&(stu2.list), &head_list);
stu3.num = 3;
stu3.english = 93;
stu3.math = 83;
list_add_tail(&(stu3.list), &head_list);
/*3.遍歷節點並取出節點*/
/*
* 基本思路:通過decltype獲取數據類型,並定義一個位於0地址的該數據,
* 通過計算指針域到0地址處的差值,可以得到數據入口與指針
* 域的差值,從而可以通過指針域-差值的方式來讀取節點中的
* 數據,從而達到通用雙向循環鏈表的作用,此處是精華。
*/
list_for_each(pos, (&head_list))
{
decltype(tmp) test = 0;
unsigned i = (unsigned)(&(test->list)) - (unsigned)test;
tmp = (decltype(tmp))((unsigned)pos - i);
cout << "No." << tmp->num << " " << "english is " << tmp->english << "," << "math is " << tmp->math << endl;
}
/*4.刪除節點*/
list_del(&(stu1.list));
list_del(&(stu2.list));
list_del(&(stu3.list));
/*5.再次取出節點,檢驗節點是否刪除*/
list_for_each(pos, (&head_list))
{
decltype(tmp) test;
unsigned i = (unsigned)(&(test->list)) - (unsigned)test;
tmp = (decltype(tmp))((unsigned)pos - i);
cout << "No." << tmp->num << " english is " << tmp->english << ",math is " << tmp->math << endl;
}
system("pause");
return 0;
}
//#define l_offsetof(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER)
//#define container_of(ptr, type, member) ({const typeid(((type *)0)->member)*_mptr = (ptr); (type*)((char*)_mptr-l_offsetof(type,member));})
/*****************************************************
Function name: list_entry
Function: get the data of list
Parameters:
list_head *prt: the &struct list_head pointer
type: the type of the struct this embeded in
member: the name of the list_struct within the struct
*******************************************************/
//#define list_entry(ptr, type, member) ({type *test; unsigned i = test - &(test->member); ptr - i;})
遇到的問題:
1.
此處的使用到了強制轉換,能不能想辦法去掉強制轉換,暫時還沒想到辦法,之後想到了再來解決。