Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 765
systemsfault Avatar asked Apr 20 '10 08:04

systemsfault


People also ask

How are macros expanded in C?

The LENGTH and BREADTH are called the macro templates. The values 10 and 20 are called macro expansions. When the program run and if the C preprocessor sees an instance of a macro within the program code, it will do the macro expansion. It replaces the macro template with the value of macro expansion.

What is a macro in Linux?

More Linux resources In Vim, a macro is a feature that allows you to record a sequence of commands that you use to perform a given task. You then execute that macro many times to repeat the same job in an automated way.

How is macro expanded?

Macro expansion is an integral part of eval and compile . Users can also expand macros at the REPL prompt via the expand REPL command; See Compile Commands. Macros can also be expanded programmatically, via macroexpand , but the details get a bit hairy for two reasons. The second complication involves eval-when .

What is the use of macro expansion?

In computer programming, a macro (short for "macro instruction"; from Greek μακρο- 'long, large') is a rule or pattern that specifies how a certain input should be mapped to a replacement output. Applying a macro to an input is known as macro expansion.


4 Answers

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);
like image 174
codaddict Avatar answered Sep 21 '22 02:09

codaddict


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.

like image 37
SK-logic Avatar answered Sep 22 '22 02:09

SK-logic


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.

like image 20
Aaron Digulla Avatar answered Sep 20 '22 02:09

Aaron Digulla


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.

like image 25
Vlad Avatar answered Sep 20 '22 02:09

Vlad