内核链表:
特点:节点的指针域指向下一个节点/上一个节点的指针域,由此可以统一指针的类型,具有一般通用性,使用指针域跟数据入口地址【设为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.
此处的使用到了强制转换,能不能想办法去掉强制转换,暂时还没想到办法,之后想到了再来解决。