2012-04-05 11 views
5

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:

  1. Co to jest stailhead? Wydaje się, że jest to "tylko" zdefiniowane.
  2. Jak przekazać head i entries do funkcji?
  3. 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); 
} 
+0

Przejdź do odpowiednich nagłówków i zobacz, co robią 'STAILQ_HEAD',' STAILQ_INIT' rozwiń na –

+2

Lub po prostu użyj 'gcc -E'. BTW, ten sposób użycia makr jest użyteczny do symulacji generycznych w C. –

+0

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

Odpowiedz

7

Najpierw należy przeczytać this się trzymać Co te makra. A następnie przejdź do queue.h. Dostaniesz tam swój skarb!

znalazłem kilka złotych monet na you-

#define STAILQ_HEAD(name, type)           \ 
struct name {               \ 
     struct type *stqh_first;/* first element */      \ 
     struct type **stqh_last;/* addr of last next element */   \ 
} 

Pozwala kopać w trochę głębsze i odpowiedzieć na pytania

Co stailhead? Wydaje się, że jest to "tylko" zdefiniowane.

#define STAILQ_HEAD(name, type)           \ 
struct name {               \ 
     struct type *stqh_first;/* first element */      \ 
     struct type **stqh_last;/* addr of last next element */   \ 
} 
STAILQ_HEAD(stailhead, entry) head = 
STAILQ_HEAD_INITIALIZER(head); 
struct stailhead *headp;   /* Singly-linked tail queue head. */ 

Więc stailhead jest strukturą

Jak przekazać głowę i wpisy do funkcji?

#define STAILQ_ENTRY(type)            \ 
struct {                \ 
     struct type *stqe_next; /* next element */      \ 
} 

Więc entries i head (jak wyjaśniono wcześniej) są tylko struktury i można przekazać je po prostu jak przekazać inne struktury. &structure_variable

Jakiego typu jest głowa, jak mogę zadeklarować wskaźnik?

Już wyjaśnione!

Przeczytaj this man page za ładne ładne przykłady.

+0

'człowiek 3 kolejka' (XXX głupie dopełnienie, aby stackoverflow zaakceptować mój komentarz) –

+1

@ConradMeyer Dzięki mate. Dodałem link strony podręcznika! –

+0

Dzięki Pavan, Dzięki za poświęcenie czasu na odpowiedź. Twoje odpowiedzi są naprawdę pomocne. – Raj