Какая польза от while (0), когда мы определяем макрос?

Возможный дубликат:
Операторы Do-While и if-else в макросах C / C ++

Я читаю kernel ​​linux, и я нашел много таких макросов:

#define INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0) 

Почему они используют это, а не определяют его просто в {}?

Вы можете следовать за ним точкой с запятой и заставлять ее выглядеть и действовать как функция. Он также работает с правилом if / else.

Без времени (0) ваш код выше не будет работать с

 if (doit) INIT_LIST_HEAD(x); else displayError(x); 

так как точка с запятой после макроса будет «есть» предложение else, и выше не будет даже компилироваться.

Он позволяет группировать несколько операторов в один макрос.

Предположим, вы сделали что-то вроде:

 if (foo) INIT_LIST_HEAD(bar); 

Если макрос был определен без инкапсуляции do {…} while (0);, приведенный выше код будет расширяться до

 if (foo) (bar)->next = (bar); (bar)->prev = (bar); 

Это явно не то, что было предназначено, так как только первый оператор будет выполнен, если foo имеет место. Второй оператор будет выполнен независимо от того, выполняется ли foo.

Изменить: дальнейшее объяснение на http://c-faq.com/cpp/multistmt.html и http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/cpp/Swallowing-the-Semicolon.html # глотание-The-Запятая

  • Встроенная функция v. Макрос в C - Что такое служебные данные (память / скорость)?
  • C и использование аргументов в круглых скобках
  • Скопируйте рабочий лист Excel и поддерживайте относительную ссылку на ячейки в формулах
  • Как скопировать только гиперссылку (а не текст) в другую ячейку?
  • Сохранение макросов vim
  • Встроенные функции против макросов препроцессора
  • Как создать новую строку в макросе cpp?
  • Выполнить class от имени?
  • Каковы последствия макросов linux __user?
  • Выход препроцессора
  • Могу ли я записывать / воспроизводить macros в Visual Studio 2012/2013/2015/2017?
  • Давайте будем гением компьютера.