views:

265

answers:

5

I generally have ignored using macros while writing in C but I think I know fundamentals about them. While i was reading the source code of list in linux kernel, i saw something like that:

#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)

(You can access the remaining part of the code from here.)

I didn't understand the function of ampersands(I don't think they are the address of operands here) in LIST_HEAD_INIT and so the use of LIST_HEAD_INIT in the code. I'd appreciate if someone can enlighten me.

+3  A: 

They are address-of operators here. The linked lists in the kernel avoid null pointers to denote the end of a list. Therefore, the header must be initialized with some valid pointer. In this implementation, if the "head" or "tail" pointer point to the address of the list header, the list is considered empty.

Aaron Digulla
+1  A: 

The macro itself seems to be not used in the list.h.

I assume & mean indeed addresses in the code. The struct list_head contains two pointers, so it should be quite natural for declaration struct list_head name = LIST_HEAD_INIT(name) (see macro LIST_HEAD) to obtain a pair of pointers as initializer.

Vlad
A: 

That's exactly what they are, the ampersands take the address of the parameter and store them in both in the "head" and "next" list fields. Couldn't tell you why, since I didn't find an actual use of this macro, but that's what it does.

Blindy
+5  A: 

Every time you're in doubt on what macro is actually doing, you can ask 'gcc -E' to expand it for you.

In this case it just initialise a list structure with pointers to itself.

SK-logic
+1 for the -E option idea
Dacav
Wow didn't know this option before. Thanx
systemsfault
+5  A: 

To know what actually is happening we need the definition of struct list_head:

struct list_head {
        struct list_head *next, *prev;
};

Now consider the macros:

#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)

If in the code I write LIST_HEAD(foo) it gets expanded to:

struct list_head foo = { &(foo) , &(foo)}

which represents an empty doubly linked list with a header node where the next and prev pointers point to the header node itself.

It is same as doing:

struct list_head foo;
foo.next = &foo;
foo.prev = &foo;

So effectively these macros provide a way to initialize a doubly linked list.

And yes, & is used here as the address of operator.

EDIT:

Here is a working example

In the link provided by you. You had:

struct list_head test = LIST_HEAD (check);

which is incorrect. You should have:

LIST_HEAD (check);
codaddict
@unicornaddict i considered the similar scenario before asking this question. But i got an error when tried this code: http://pastebin.com/P2cCfNbQ . I tried to give void, int, macro etc... and got errors in those conditions too.
systemsfault
@holydiver: I've updated my answer with a link to **working example** and have also pointed the error in *your* code.
codaddict
@unicornaddict thanx now i've really got it.
systemsfault