6

I am trying to wrap my head around the concept of using macros to define data structure operations. The following code is a simple example to use the built in list library in FreeBSD. In the library all operations are defined as macros. I have seen this approach in couple of other libraries also.

I can see that this has some advantages eg. being ability to use any data structure as an element in the list. But I do not quite understand how this works. For example:

  1. What is stailhead? This seems to be "just" defined.
  2. How to pass head and entries to a function?
  3. What type is head, how can I declare a pointer to it?

Is there a standard name for this technique which I can use to search google, or any book which explains this concept? Any links or good explanation as to how this technique works will be much appreciated.

Thanks to Niklas B. I ran gcc -E and got this definition for head

struct stailhead {
  struct stailq_entry *stqh_first;
  struct stailq_entry **stqh_last; 
} head = { ((void *)0), &(head).stqh_first };

and this for stailq_entry

struct stailq_entry {
 int value;
 struct { struct stailq_entry *stqe_next; } entries;
};

So I guess head is of type 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);
}
Community
  • 1
  • 1
Raj
  • 85
  • 1
  • 5

1 Answers1

7

First read this to get a hold what these macros do. And then go to queue.h. You'll get your treasure trove there!

I found a few gold coins for you-

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

Lets dig in a bit deep and answer your questions

What is stailhead? This seems to be "just" defined.

#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. */

So stailhead is a structure

How to pass head and entries to a function?

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

So entries and head ( as explained before ) are just structures and you can pass them just as you pass other structures. &structure_variable

What type is head, how can I declare a pointer to it?

Already explained!

Read this man page for nice pretty examples.

Pavan Manjunath
  • 27,404
  • 12
  • 99
  • 125