2013-05-17 3 views
1

Я смотрю на двух взаимосвязанных реализаций списка (queue.h [source] и utlist.h [source]), и у меня есть несколько вопросов, касающихся их соответствующих реализаций:Некоторые связный список C макро вопросы

  1. Что такое _Q_INVALIDATE все о в queue.h? Я полагаю, что это часть некоторой отладки, но я не совсем понимаю логику макроса define.
  2. Обе реализации предлагают FOREACH и FOREACH_SAFE. Первое прямо, но какова логика второго? Кроме того, если первое небезопасно, почему оно было реализовано в первую очередь?
  3. Почему queue.h реализовал свою структуру как имеющую разные типы для next и prev (struct *le_next и struct **le_prev)?
  4. В обеих реализациях, почему здесь вставлены дополнительные скобки? Например. вокруг head в #define LIST_FIRST(head) ((head)->lh_first)
+1

Для # 4 см. [Использование круглых скобок внутри макросов вокруг имен параметров] (https://www.securecoding.cert.org/confluence/display/seccode/PRE01-C.+Use+parentheses+within+macros+around + параметр + имена) –

+0

@MichaelBurr: Аааа, я понял это сейчас. Благодарю. – c00kiemonster

ответ

4

К вопросу 1:

_Q_INVALIDATE макрос, который устанавливает указатель, который больше не будет использоваться для значения -1. Цель состоит в том, что если он используется впоследствии, отладка будет проще, поскольку использование указателя приведет к немедленному сбою. В режиме без отладки макрос ничего не делает, поэтому указатель остается с его текущим значением - если есть ошибка, которая приводит к использованию указателя, проблема может быть гораздо более тонким дефектом.

К вопросу 2:

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

К вопросу 3:

Это делает его легче добавить новый элемент перед текущим или удалить текущий элемент из списка, не заботясь о том текущий элемент находится во главе списка (и поэтому только «указывается» на указатель списка), или если текущий элемент находится в другом месте списка (и, следовательно, указывается указателем другого элемента le_next). Если le_prev были struct type*, то для работы с первым элементом в списке потребуется специальный код случая. Так как le_prev является struct type**, он может относиться к простому struct type* (например, указателю на указатель) так же легко, как и struct type*, который встроен при некотором произвольном смещении внутри type (например, ссылки le_next в каждом элементе).

Вопрос 4 ответил на комментарий выше.

+0

Превосходно. Я действительно не получил -1 часть о Вопросе 1. Довольно умный способ сигнализировать неправильное использование указателей. Большое спасибо! – c00kiemonster

Смежные вопросы