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