I. Limitations of the General list.
When we learn the data structure, the operation of the linked list is much the same, although the data structure uses the abstract type description algorithm, but the implementation of the method itself has caused the basic operation of the list and user-defined data type (ELEMTYPE) produced a high degree of coupling, data types and the operation of the list of such "binding", Downgrade the reusability of the code, each time the linked list is applied to the new situation, the source code to ensure that the linked list and the new data type "binding", a large number of repeated operations, it is inevitable that a variety of errors. We want a list with a universal type that will divide the data type from the list operation, which requires the so-called universal So to name it).
The implementation of the linked list comes from Nginx, but the source code is not read by me personally, but by video, thanks to the video author @ Flying brother (although not able to ...).
There are some minor errors in the video and I will correct them in the text.
Two. What is a universal linked list
The so-called universal linked list, the linked list, has no independence from the user-defined data type (node type). We can write it all at once.
Advantages: Versatility, low overhead,
Cons: not responsible for memory management, large use of macros, no type check
Three. Principle of generality.
Before the use of the general list, there have been this annoyance, have thought, how to do "General", until the understanding of this method, can not help simply astounding, this law step by step, hidden mystery, is the crystallization of wisdom, C language masterpiece ... (10000 words omitted here)
To get to the point, the first thing to note is that to complete this list, you only need a header file.
First, this method defines a struct
struct list_s list, *Plist; struct list_s{ Plist prev, next;};
This structure is the clue that runs through the whole play. Using this list requires defining a list type of data in the structure, like this:
struct { int A; List List;} TEST,*ptest;
The structure of the whole list is connected by the list.
The core idea is that we manipulate the list (the red part) and we can logically delete it from the linked list, inserting an element (so that the implementation of this list is unrelated to memory management)
In fact, we are the equivalent of managing a linked list of elements that are just their predecessor after the successor pointer
It looks good, although the list members can "carry" other data to find the right location in the list, but how do we access that data?
We manage the list members, we can know the information is the address of the list, the blue arrow points to the place is the list member is the address, to access the data, we need to know the entire structure of the first address,
The position of the red triangle is the first address of the entire structure. We might as well give an example
In this case, the size of data can be calculated by 2004h-2000h = 4H, and this is also the offset of the list member
Know the offset, know the first address of the list, you know the structure of the first address, and so on! It seems wrong--! You don't know that 2000H, you know, it's still a yarn!
Well, it's a problem, but the bottom way is really great!
typedef struct { int A; List List;} TEST, *ptest; TEST t = {1234 ,{null, NULL}}; Plist l = &t.list;printf ( " Span style= "color: #800000;" >%d\n , & ((PTEST) 0 ) list); // get offset! printf ( %d , ((PTEST) ((char *) L-(char *) & ((PTEST) 0 )->list))->a);
The key is to get to the offset, and the rest is yielded,
& ((PTEST)0)->list
It's a magical code, isn't it, let's analyze it.
0 Treat 0 as an address
((PTEST) 0 cast to custom struct type
((PTEST) 0)->list
& ((PTEST) 0)->list Get the address of the list member
Since the address starts at 0, the address of the list is its offset in the struct
Having understood the above principles, we have mastered the core methods of the universal linked list.
Four, to achieve
List.h
#ifndef _list_h_#define_list_h_typedefstructlist_s List, *Plist;structlist_s{Plist prev, next;};//Initialize H: Head node pointer#defineListinit (h) Do{(h)->prev =NULL; (h)->next =NULL; } while(0)//h: Head node pointer l: Pointer to a list type member in a custom struct#defineListheadinsert (h,l) Do{(l)->prev =(h); (l)->next = (h)Next; (h)->next =(l); } while(0)//#defineListtailinsert (h,l) Do{Plist T=h; while(t->next) T = t->Next; (l)->prev =(t); (l)->next = (t)Next; (t)->next =(l); } while(0)//L: Pointer to the list member of the node to read//Struct_type: The type name of the custom struct body//member name of the Struct_field:list type member (variable name)#defineListgetdata (L,struct_type, Struct_field) \((Struct_type*)((Char*) (L)-offsetof (Struct_type,struct_field)))//Pointer to the list of nodes to delete#defineListdelet (L) Do{ if((l)->next = =NULL) {(L)->prev->next = (L)Next; (l)->prev =NULL; }Else{(l)->prev->next = (L)Next; (l)->next->prev = (L)prev; } } while(0)#endif
Code for testing:
#include <stdio.h>#include"list.h"typedefstruct{ intA; List List;} TEST,*PTEST;intMainintargcChar**argv) { /*TEST t = {1234,{null, NULL}}; Plist L = &t.list; int n = & ((TEST) 0). List; & ((PTEST) 0)->list; printf ("%d\n", & ((PTEST) 0)->list); printf ("%d", ((PTEST) ((char*) L-(char*) & ((PTEST) 0)->list)),->a); printf ("%d", ((PTEST) ((char*) L-offsetof (test,list))),->a); */TEST test1= {1234, {null, NULL}}; TEST test2= {2234, {null, NULL}}; TEST test3= {3234, {null, NULL}}; List Head; Listinit (&head); Listtailinsert (&head,&test1.list); Listtailinsert (&head,&test2.list); Listtailinsert (&head,&test3.list); List* Temp =Head.next; for(temp = head.next; Temp! = NULL; temp = temp->next) {PTEST data_addr=Listgetdata (temp,test,list); printf ("%d\n", data_addr->a); } //printf ("%p,%p \ n", Test2.list.prev, Test2.list.next);Listdelet (&test3.list); for(temp = head.next; Temp! = NULL; temp = temp->next) {PTEST data_addr=Listgetdata (temp,test,list); printf ("%d\n", data_addr->a); } return 0;}
Five. Conclusion
And there's no conclusion.
Implementation of Universal linked list