Я обычно игнорировал макросы использования при записи в 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 в коде. Я ценил бы, если кто-то может просветить меня.
Чтобы узнать, что на самом деле происходит, нам нужно определение 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);
Это именно то, что они есть, амперсанды принимают адрес параметра и сохраняют их в обоих полях списка "head" и "next". Не могу сказать почему, так как я не нашел фактического использования этого макроса, но это то, что он делает.
Каждый раз, когда вы сомневаетесь, что на самом деле делает макрос, вы можете попросить 'gcc -E' расширить его для вас.
В данном случае он просто инициализирует структуру списка с указателями на себя.
Здесь они являются операторами адресов. Связанные списки в ядре избегают нулевых указателей для обозначения конца списка. Следовательно, заголовок должен быть инициализирован некоторым допустимым указателем. В этой реализации, если указатель «головы» или «хвоста» указывает на адрес заголовка списка, список считается пустым.
Кажется, что сам макрос не используется в list.h
.
Я полагаю, что и
действительно означают адреса в коде. struct list_head
содержит два указателя, поэтому это должно быть вполне естественно для объявления struct list_head name = LIST_HEAD_INIT (name)
(см. Макрос LIST_HEAD
) для получения пары указателей в качестве инициализатора.