Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c programming #define struct { } declaring

Tags:

c

glibc

I was looking at Glibc codes. Some codes of glibc's queue caught my attention. I couldn't give a meaning to this struct definition. This struct doesn't have a name. Why? How does it work?

#define LIST_ENTRY(type)                        \
struct {                                \
    struct type *le_next;   /* next element */          \
    struct type **le_prev;  /* address of previous next element */  \
}

Source

like image 794
epoxxy Avatar asked Dec 05 '22 15:12

epoxxy


2 Answers

That is actually a preprocessor macro, that could be expanded (most probably with trailing name) somewhere else.

In the comments at the start of that header file there is a reference to queue(3) man page that contains more details on that and other macros:

The macro LIST_ENTRY declares a structure that connects the elements in the list.

And an example of use:

LIST_HEAD(listhead, entry) head = LIST_HEAD_INITIALIZER(head);  
struct listhead *headp;                 /* List head. */
struct entry {  
  ...  
  LIST_ENTRY(entry) entries;      /* List. */  
  ...  
}  
*n1, *n2, *n3, *np, *np_temp;  

LIST_INIT(&head);                       /* Initialize the list. */  

n1 = malloc(sizeof(struct entry));      /* Insert at the head. */   
LIST_INSERT_HEAD(&head, n1, entries);

Being this C code (not C++), and C lacks templates, this preprocessor macro can be used to "simulate" templates (note the type parameter).

like image 69
roalz Avatar answered Dec 28 '22 06:12

roalz


It's a macro that is used to declare a struct type, with next and prev pointers to instances of a second struct type. That second type can be a parent type, so you can make a "linkable struct" like this:

struct foo {
  LIST_ENTRY(foo) list;
  int value;
};

This creates a struct foo containing a member called list which in turn is the structure in the question, with the pointers pointing at struct foo.

We can now create a little linked list of struct foos like so:

struct foo fa, fb;
fa.value = 47;
fa.list.le_next = &fb;
fa.list.le_prev = NULL;
fb.value = 11;
fb.list.le_next = NULL;
fb.list.le_prev = &fa.list.le_next;

I'm not 100% sure about the last line, but I think it kind of makes sense.

like image 39
unwind Avatar answered Dec 28 '22 07:12

unwind