C макрорасширение в коде Ядра Linux

Я обычно игнорировал макросы использования при записи в C, но я думаю, что знаю основные принципы о них. В то время как я читал исходный код списка в ядре Linux, я видел что-то как этот:

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

(Можно получить доступ к остающейся части кода отсюда.)

Я не понял функции амперсандов (я не думаю, что они - адрес операндов здесь) в LIST_HEAD_INIT и так использование LIST_HEAD_INIT в коде. Я ценил бы, если кто-то может просветить меня.

6
задан Brian Tompsett - 汤莱恩 23 February 2016 в 22:14
поделиться

5 ответов

Чтобы узнать, что на самом деле происходит, нам нужно определение struct list_head :

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

Теперь рассмотрим макросы:

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

Если в коде я напишу LIST_HEAD (foo) он расширяется до:

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

, который представляет собой пустой двусвязный список с узлом заголовка , где указатели next и prev указывают на сам узел заголовка.

Это то же самое, что делать:

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

Фактически эти макросы предоставляют способ инициализировать двусвязный список.

И да, & используются здесь как адрес оператора.

РЕДАКТИРОВАТЬ:

Вот рабочий пример

По предоставленной вами ссылке. У вас было:

struct list_head test = LIST_HEAD (check);

, что неверно. У вас должно быть:

LIST_HEAD (check);
15
ответ дан 8 December 2019 в 03:52
поделиться

Это именно то, что они есть, амперсанды принимают адрес параметра и сохраняют их в обоих полях списка "head" и "next". Не могу сказать почему, так как я не нашел фактического использования этого макроса, но это то, что он делает.

0
ответ дан 8 December 2019 в 03:52
поделиться

Каждый раз, когда вы сомневаетесь, что на самом деле делает макрос, вы можете попросить 'gcc -E' расширить его для вас.

В данном случае он просто инициализирует структуру списка с указателями на себя.

8
ответ дан 8 December 2019 в 03:52
поделиться

Здесь они являются операторами адресов. Связанные списки в ядре избегают нулевых указателей для обозначения конца списка. Следовательно, заголовок должен быть инициализирован некоторым допустимым указателем. В этой реализации, если указатель «головы» или «хвоста» указывает на адрес заголовка списка, список считается пустым.

3
ответ дан 8 December 2019 в 03:52
поделиться

Кажется, что сам макрос не используется в list.h .

Я полагаю, что и действительно означают адреса в коде. struct list_head содержит два указателя, поэтому это должно быть вполне естественно для объявления struct list_head name = LIST_HEAD_INIT (name) (см. Макрос LIST_HEAD ) для получения пары указателей в качестве инициализатора.

1
ответ дан 8 December 2019 в 03:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: