How to Implement generic linked list in C language and generic type in C Language

Source: Internet
Author: User

How to Implement generic linked list in C language and generic type in C Language

I recently looked at the Linux kernel source code and found that the list_head struct is widely used in the kernel. Baidu checked that the kernel used this struct to implement the generic type.

I think I am familiar with the linked list, and I decided to implement it myself.

The following uses Node and list_head as examples.

This is the general idea of the loop chain. (Poor painting)

We use list_head to move the linked list.

There are several problems:

First, the pointer obtained through list_head points to the list_head struct, but we actually want to use the Node struct.

Furthermore, if we want to design a generic linked list, I cannot perform any Node operations on the linked list.

Solution:

1. Find the first address of the node struct through computation. (We use a macro to implement it)

1 #define list_entry(ptr, type, member) \2     ((type *)((char *)(ptr) - (char *)(&(((type *)0)->member))))

This macro may seem messy, but we will not confuse our thinking.

We only know the entry pointer. How can we find the Node pointer?

If we can know the relative position of the entry

Actual location of Node = actual location of entry-relative location of entry.

The relative position of the entry = (& (Node *) 0)-> entry) again? Here, we first convert 0 to a pointer of the (Node *) type, then point this pointer to the entry, and finally get its address. Then we get the relative position of the entry.

Convert them into char * to perform subtraction. Finally, convert it to the Node type, and then I get the Node pointer.

2. let users define their own operations on specific data. We only provide one function interface (implemented through function pointers)

In our linked list, only the content in list_head is involved. Therefore, Node operations cannot be performed. The parameters are also list_head pointers. This requires you to use the above macro to complete the conversion from list_head to Node. We will learn about it later in the example.

 

Source code

Dclist_head.h

1 /************************************** * *********************************** 2> File Name: dlist_head.h 3> Author: gaozy 4> Mail: 44523253@qq.com 5> Created Time: 6 ******************************* **************************************** */7 8/* 9 * This is a self-implemented generic cyclic linked list 10 * users only need to add the dclist_head_t struct to their own struct to use this linked list. 11 * in use, the user needs to create a header node, and then use the init function for initialization. (Of course, You can initialize it yourself) 12 * It is very important, otherwise you cannot use this linked list. 13 * The linked list provides users with four functions. 14 * init has just been mentioned. We use it to initialize the linked list. 15 * append is a function for adding nodes to the linked list, we need to pass in the head of the linked list and the pointer 16 * treaverse in the dclist_head_t part of the new node. Just like the fire function name, it is used as a traversal chain table, it requires that we provide a function pointer 17 * which is used to operate nodes. The parameter is a pointer of the dclist_head_t type, we use the macro list_entry to obtain 18 * User-defined data types. 19 * dc_remove: This function is used to release the linked list. Similar to the treaverse function, we need to delete the j-node function by ourselves. 20 * It will release all the nodes in the linked list, except the header node. We need to release 21 */22 23 # ifndef DLIST_HEAD24 # define DLIST_HEAD25 26 # define list_entry (ptr, type, member) \ 27 (type *) (char *) (ptr)-(char *) (& (type *) 0)-> member )))) 28 29 typedef struct dclist_head {30 struct dclist_head * prev; 31 struct dclist_head * next; 32} response; 33 34 void init (response * head); 35 void append (dclist_head_t * head, optional * node); 36 void treaverse (dclist_head_t * head, void (* pfun) (dclist_head_t * node); 37 void dc_remove (dclist_head_t * head, void (* pfun) (dclist_head_t * node); 38 39 # endif

Dclist_head.c

1 /************************************** * *********************************** 2> File Name: dclist_head.c 3> Author: gaozy 4> Mail: 44523253@qq.com 5> Created Time: 6 ******************************* **************************************** */7 8 # include <stdio. h> 9 # include <stdlib. h> 10 11 # include "dclist_head.h" 12 13 14 void init (dclist_head_t * head) 15 {16 if (head! = NULL) {17 head-> prev = NULL; 18 head-> next = NULL; 19} 20} 21 22 void append (dclist_head_t * head, dclist_head_t * node) 23 {24 if (head = NULL) {25 printf ("error \ n"); 26 exit (1 ); 27} 28 29 if (head-> prev = NULL & head-> next = NULL) {30 head-> prev = node; 31 head-> next = node; 32 node-> prev = head; 33 node-> next = head; 34} else {35 dclist_head_t * tmp = head-> prev; 36 tmp-> next = node; 37 node-> prev = Tmp; 38 node-> next = head; 39 head-> prev = node; 40} 41} 42 43 void treaverse (dclist_head_t * head, void (* pfun) (dclist_head_t * node) 44 {45 if (head = NULL | head-> next = NULL) 46 return; 47 48 dclist_head_t * tmp = head-> next; 49 while (tmp! = Head) {50 pfun (tmp); 51 tmp = tmp-> next; 52} 53} 54 55 void dc_remove (dclist_head_t * head, void (* pfun) (dclist_head_t * node) 56 {57 treaverse (head, pfun); 58}


Test code

Main. c

1 /************************************** * *********************************** 2> File Name: main. c 3> Author: gaozy 4> Mail: 44523253@qq.com 5> Created Time: 6 ******************************* **************************************** */7 8 # include <stdio. h> 9 # include <stdlib. h> 10 11 # include "dclist_head.h" 12 13 typedef struct {14 int id; 15 dclist_head_t entry; 16} stud Ent_t; 17 18 void print (dclist_head_t * ptr) 19 {20 student_t * stu = list_entry (ptr, student_t, entry); 21 if (stu = NULL) 22 return; 23 printf ("student id = % d \ n", stu-> id); 24} 25 26 void free_node (dclist_head_t * ptr) 27 {28 if (ptr = NULL) 29 return; 30 31 student_t * node = list_entry (ptr, student_t, entry); 32 free (node); 33} 34 35 student_t * make_node (int id) 36 {37 student_t * stu = (student_t *) mall Oc (sizeof (student_t); 38 if (stu! = NULL) {39 stu-> id = id; 40} 41 42 return stu; 43} 44 45 int main (void) 46 {47 dclist_head_t list; 48 49 init (& list); 50 51 int I; 52 student_t * stu; 53 for (I = 0; I <5; I ++) {54 stu = make_node (I); 55 if (stu! = NULL) 56 append (& list, & stu-> entry); 57} 58 59 60 treaverse (& list, print); 61 dc_remove (& list, free_node ); 62 63 64 return 0; 65}

The level is limited. Please give me more advice.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.