Próbuję owijać głowę wokół koncepcji używania makr do definiowania operacji struktury danych. Poniższy kod jest prostym przykładem użycia wbudowanej biblioteki list w FreeBSD. W bibliotece wszystkie operacje są zdefiniowane jako makra. Widziałem to podejście także w kilku innych bibliotekach.Używanie makr w C do definiowania struktur danych
Widzę, że ma to pewne zalety, np. możliwość korzystania z dowolnej struktury danych jako elementu na liście. Ale nie do końca rozumiem, jak to działa. Na przykład:
- Co to jest
stailhead
? Wydaje się, że jest to "tylko" zdefiniowane. - Jak przekazać
head
ientries
do funkcji? - Jakiego typu jest
head
, w jaki sposób mogę zadeklarować wskaźnik?
Czy istnieje standardowa nazwa tej techniki, której mogę używać do wyszukiwania w Google lub jakiejkolwiek książki wyjaśniającej tę koncepcję? Wszelkie linki lub dobre objaśnienia dotyczące działania tej techniki będą mile widziane.
Dzięki Niklas B. Pobiegłem gcc -E
i dostał tę definicję dla head
struct stailhead {
struct stailq_entry *stqh_first;
struct stailq_entry **stqh_last;
} head = { ((void *)0), &(head).stqh_first };
i to dla stailq_entry
struct stailq_entry {
int value;
struct { struct stailq_entry *stqe_next; } entries;
};
Więc myślę head
jest typu struct stailhead
.
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
struct stailq_entry {
int value;
STAILQ_ENTRY(stailq_entry) entries;
};
int main(void)
{
STAILQ_HEAD(stailhead, stailq_entry) head = STAILQ_HEAD_INITIALIZER(head);
struct stailq_entry *n1;
unsigned i;
STAILQ_INIT(&head); /* Initialize the queue. */
for (i=0;i<10;i++){
n1 = malloc(sizeof(struct stailq_entry)); /* Insert at the head. */
n1->value = i;
STAILQ_INSERT_HEAD(&head, n1, entries);
}
n1 = NULL;
while (!STAILQ_EMPTY(&head)) {
n1 = STAILQ_LAST(&head, stailq_entry, entries);
STAILQ_REMOVE(&head, n1, stailq_entry, entries);
printf ("n2: %d\n", n1->value);
free(n1);
}
return (0);
}
Przejdź do odpowiednich nagłówków i zobacz, co robią 'STAILQ_HEAD',' STAILQ_INIT' rozwiń na –
Lub po prostu użyj 'gcc -E'. BTW, ten sposób użycia makr jest użyteczny do symulacji generycznych w C. –
Na pierwszy rzut oka uważam, że użycie STAILQ_HEAD_INITIALIZER w definicji, a później STAILQ_INIT jest zbędny. Uważam, że robią to samo. – abelenky