C Macro Extension in Linux Kernel Code

I generally ignored the use of macros when writing to C , but I think I know the basic principles about them. While I was reading the list source code in the linux kernel, I saw something like this:

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

(You can access the rest of the code from here. )

I did not understand the function of ampersands (I don’t think they are the operand addresses here) in LIST_HEAD_INIT and therefore use LIST_HEAD_INIT in the code. I would appreciate it if someone could enlighten me.

+6
c macros list linux c-preprocessor
source share
5 answers

To find out what really happens, we need a 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 expands to:

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

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

This is the same as doing:

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

Thus, these macros provide a way to initialize a doubly linked list.

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

EDIT:

Here is a working example

In the link provided by you. You had:

 struct list_head test = LIST_HEAD (check); 

which is wrong. You must have:

 LIST_HEAD (check); 
+14
source share

Every time you doubt what the macro actually does, you can ask "gcc -E" to expand it for you.

In this case, it simply initializes the list structure with pointers to itself.

+8
source share

Here they are the addresses of the operators. Linked lists in the kernel avoid zeros to indicate the end of the list. Therefore, the header must be initialized with some valid pointer. In this implementation, if the "head" or "tail" pointer points to the address of the list header, the list is considered empty.

+3
source share

The macro itself is not used in list.h

I assume & really means addresses in code. struct list_head contains two pointers, so to declare a struct list_head name = LIST_HEAD_INIT(name) (see LIST_HEAD macro), it should be natural to get a couple of pointers as an initializer.

+1
source share

Exactly what they are, ampersands accept the address of the parameter and store them both in the "head" and "next" fields. I can’t say why, since I did not find the actual use of this macro, but what does it do.

0
source share

All Articles