2009-05-29 2 views
113

Можно создать дубликат:
Do-While and if-else statements in C/C++ macrosЧто нужно делать во время (0), когда мы определяем макрос?

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

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

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

ответ

131

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

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

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

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

+5

Но вопрос в OP остается в силе. Почему не просто {(ptr) -> next ...} вместо do {(ptr) -> next ...} while (0) ;? –

+26

arno объяснил это. Он будет расширяться до «{(ptr) -> next ...};" таким образом, заявление, за которым следует второе утверждение. Если синтаксис, однако, есть выражение if (expression) statement else ". Друг не будет связан с каким-либо, если бы вы написали оператор выражения if (expression) "(один" {...} "и один оператор"; "). –

+3

Как сказал Амо, это умный трюк, позволяющий макросу * быть * выражением C, который должен заканчиваться точкой с запятой. Это делает макрос действовать точно так же, как вызов функции, если речь идет о построении и завершении оператора (с ';'). – Eddie

41

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

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

if (foo) 
    INIT_LIST_HEAD(bar); 

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

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

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

Edit: Дальнейшее объяснение в 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

+7

Это не объясняет do .. while (0) часть макроса, просто использование {} брекетов. – SPWorley

+0

do {} в то время как (0) часть объясняется в сообщении, это один из них. – adobriyan

+1

SPWorley, adobriyan: На самом деле, похоже, автор этого сообщения добавил ссылки, объясняющие do {} while (0). – Jamer

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