Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using macros in C to define data structures

Tags:

c

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);
}
like image 602
Raj Avatar asked Apr 05 '12 15:04

Raj


People also ask

What is macro in data structure?

A macro is a piece of code in a program that is replaced by the value of the macro. Macro is defined by #define directive.

Can you use macros in C?

Overview. Macro in C programming is known as the piece of code defined with the help of the #define directive. Macros in C are very useful at multiple places to replace the piece of code with a single value of the macro. Macros have multiple types and there are some predefined macros as well.

Can I #define in a macro?

(1) You can define a macro of a macro as in a macro containing another macro. (2) However, you cannot define a macro of a macro like #define INCLUDE #define STDH include <stdio.

What is the purpose of macro in C?

In C, the macro is used to define any constant value or any variable with its value in the entire program that will be replaced by this macro name, where macro contains the set of code that will be called when the macro name is used in the program.


1 Answers

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.

like image 56
Pavan Manjunath Avatar answered Oct 03 '22 23:10

Pavan Manjunath