开发者

C macro expansion in Linux Kernel code

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.


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);


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.


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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜