c / expert
Snippet
Intrusiver Container-Aufbau mittels Struktur-Element-Offset-Berechnung
Intrusive Container betten Listen-Strukturen direkt in Datenobjekte ein (wie in Kernel-Architekturen). Mithilfe von Zeigerarithmetik und der offsetof-Makrologik wird der übergeordnete Objektzeiger dynamisch aus eingebetteten Knotenzeigern ermittelt, ohne dass dynamische Knoten-Speicherallokationen erforderlich sind.
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
#include <stdio.h>#include <stddef.h>struct ListHead {struct ListHead* next;};#define container_of(ptr, type, member) \((type *)((char *)(ptr) - offsetof(type, member)))struct Task {int priority;struct ListHead node;};int main(void) {struct Task t = { .priority = 10 };struct ListHead* ptr = &t.node;struct Task* retrieved = container_of(ptr, struct Task, node);printf("Retrieved task priority: %d\n", retrieved->priority);return 0;}
Erklärung
1
#define container_of(ptr, type, member) ...
Berechnet den übergeordneten Strukturzeiger durch Subtraktion des Byte-Offsets vom eingebetteten Zeiger.
2
offsetof(type, member)
Standard-Makro, das den exakten Byte-Offset des angegebenen Strukturelements von der Basis zurückgibt.
3
struct Task { int priority; struct ListHead node; };
Bettet den generischen intrusiven Container-Knoten direkt in die eigene Task-Struktur ein.
4
struct Task* retrieved = container_of(ptr, struct Task, node);
Stellt die übergeordnete Task-Objektreferenz aus dem einzelnen ListHead-Zeiger sicher wieder her.