Linux 内核通用链表
链表的结点不能包含万物,那么就让万物来包含结点
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 遍历链表
#define list_for_each(n,head)\
for(n=head->next;head!=n;n=n->next)
下面两句是重点!!!!!!!!!!!!!!!!
//计算结构成员member所在结构中的距离第一个成员地址编号的差值
#define offset(type,member) ((int)&(((type*)0)->member))
//计算返回实际的结构成员指针所在结构变量的首地址
#define node_to_obj(node,type,member)\
((type*)((void*)node-offset(type,member)))
//第二种遍历
#define list_for_each_entry(ojb,head,member)\
for(obj = node_to_obj(head->next,typeof(*obj),member);\
head!= &obj->member;\
obj = node_to_obj(obj->member.next,typeof(*obj),member))
typedef struct Node
{
struct Node* prev;
struct Node* next;
}Node;
// 创建链表
Node* create_list(void)
{
Node* head = malloc(sizeof(Node));
head->next = head;
head->prev = head;
return head;
}
void _add_list(Node* p,Node* n,Node* node)
{
p->next = node;
n->prev = node;
node->next = n;
node->prev = p;
}
// 头添加
void add_head_list(Node* head,Node* node)
{
_add_list(head,head->next,node);
}
//尾添加
void add_tail_list(Node* head,Node* node)
{
_add_lista(head->prev,head,node);
}
//删除结点
void _del_list(Node* node)
{
node->next->prev = node->prev;
node->prev->next = node->next;
node->next = node;
node->prev = node;
}
//判断链表是否为空
bool empty_list(Node* head)
{
return head->next == head;
}
//头删除
Node* del_head_list(Node* head)
{
if(empty_list(head)) return NULL;
Node* temp = head->next;
_del_list(temp);
return temp;
}
//尾删除
Node* del_head_list(Node* head)
{
if(empty_list(head)) return NULL;
Node* temp = head->prev;
_del_list(temp);
return temp;
}
/* 下面是用户编写的代码 */
typedef struct Student
{
Node node;
char name[20];
char sex;
char age;
float score;
int id;
}Student;
int main(int argc,const char* argv[])
{
Node* head = create_list();
for(int i=0; i<10; i++)
{
Student* stu = malloc(sizeof(Student));
sprintf(stu->name,"hehe%d",i);
stu->sex = i%2?'w':'m';
stu->age = i+18;
stu->score = rand()%100;
stu->id = 1000+i;
add_head_list(head,&(stu->node));
}
Node* n = NULL;
list_for_each(n,head)
{
Student* stu = (Student*)n;
printf("%s %c %hhd %g %d\n",
stu->name,stu->sex,stu->age,stu->score,stu->id);
}
}