c / expert
Snippet
Intrusive verkettete Listen mittels offsetof und container_of
Intrusive verkettete Listen betten Knoten-Zeiger direkt in Nutzdaten-Strukturen ein, anstatt Nutzdaten-Zeiger in separaten Listenknoten zu verpacken. Das `container_of`-Makro nutzt `offsetof` aus `<stddef.h>` für Zeigerarithmetik: Es castet die Knoten-Adresse in einen Byte-Zeiger und subtrahiert den Struktur-Offset, um den übergeordneten Elternstruktur-Zeiger ohne Heap-Allokationen wiederherzustellen.
snippet.c
c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>#include <stddef.h>#define container_of(ptr, type, member) \((type *)((char *)(ptr) - offsetof(type, member)))struct list_node {struct list_node *next;};struct task {int priority;const char *name;struct list_node node;};int main(void) {struct task t1 = { .priority = 1, .name = "Cleanup", .node = { NULL } };struct list_node *node_ptr = &t1.node;struct task *recovered_task = container_of(node_ptr, struct task, node);printf("Task Name: %s, Priority: %d\n", recovered_task->name, recovered_task->priority);return 0;}
Erklärung
1
#define container_of(ptr, type, member) \
Definiert ein Makro zur Berechnung des Elternstruktur-Zeigers ausgehend von einer Member-Adresse.
2
((type *)((char *)(ptr) - offsetof(type, member)))
Castet Member-Zeiger in Byte-Zeiger und subtrahiert den Byte-Offset des Members innerhalb des Typs.
3
struct task *recovered_task = container_of(node_ptr, struct task, node);
Ruf Makro auf, um die Elternadresse der struct task aus der eingebetteten Knotenadresse zu berechnen.