I saw an interesting design for a doubly-linked-list inside the Pintos operating system and I don't quite understand how it was able to achieve this behavior. I wrote a small adaptation to demo what I'm referring to.
#include <stdio.h>
#include <stdint.h>
#include "list.h"
struct foo {
int x;
struct list_node node;
};
int main()
{
struct list list;
list_initialize(&list);
struct foo n1 = {1, NULL};
list_push_back(&list, &n1.node);
struct list_node *e = list_get_front(&list);
struct foo *ptr = list_entry(e, struct foo, node);
printf("%d", ptr->x);
return 0;
}
In essence, list.h
implements two structures; namely, list
and list_node
. A list can be made for any arbitrary struct so long as the struct includes a list_node
field. A reference to the structure can be returned by passing a pointer to it's list_node
using the following macro defined in list.h
.
#define list_entry(LIST_NODE, STRUCT, MEMBER) \
((STRUCT *) ((uint8_t *) &(LIST_NODE)->next \
- offsetof (STRUCT, MEMBER.next)))