Что делать во время (0), когда мы определяем макрос?
Возможный дубликат:
Операторы Do-While и if-else в макросах C/С++
Я читаю ядро linux, и я нашел много таких макросов:
#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
Почему они используют это, а не определяют его просто в {}?
Ответы
Ответ 1
Вы можете следовать за ним точкой с запятой и заставлять ее выглядеть и действовать скорее как функция.
Он также корректно работает с правилами if/else.
Без времени (0) ваш код выше не будет работать с
if (doit)
INIT_LIST_HEAD(x);
else
displayError(x);
поскольку точка с запятой после макроса будет "есть" предложение else, и выше не будет даже компилироваться.
Ответ 2
Он позволяет группировать несколько операторов в один макрос.
Предположим, вы сделали что-то вроде:
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#Swallowing-the-Semicolon