Ответ 1
http://bytes.com/groups/c/219859-do-while-0-macro-substitutions
Андрей Тарасевич:
Вся идея использования версии "do/while" заключается в создании макроса, который будет расширяется в регулярный оператор, а не в составной оператор. Это сделанные для того, чтобы использовать макрос функциональных стилей с использование обычных функций во всех контекстах.
Рассмотрим следующий эскиз кода
if (<condition>)
foo(a);
else
bar(a);
где "foo" и "bar" являются обычными функциями. Теперь представьте, что вы как заменить функцию 'foo' макросом вышеуказанной природы
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
Теперь, если ваш макрос определен в соответствии со вторым подходом (просто '{' и '}') код больше не будет компилироваться, потому что 'true' ветвь "if" теперь представлена составной инструкцией. И когда вы поместите ';' после этого составного заявления вы закончили целое 'if' , тем самым осировая ветвь "else" (следовательно, ошибка компиляции).
Один из способов исправить эту проблему - запомнить не ставить ';' после макрос "invocations"
if (<condition>)
CALL_FUNCS(a)
else
bar(a);
Это будет компилироваться и работать как ожидалось, но это не равномерно. более элегантным решением является обеспечение того, чтобы макрос расширялся до обычного выражение, а не составное. Один из способов достижения этого - определить макрос следующим образом
#define CALL_FUNCS(x) \
do { \
func1(x); \
func2(x); \
func3(x); \
} while (0)
Теперь этот код
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
будет скомпилирован без проблем.
Однако обратите внимание на небольшое, но важное различие между моим определением
из CALL_FUNCS
и первой версии вашего сообщения. Я не поставил
;
после } while (0)
. Полагая ;
в конце этого определения
немедленно уничтожит всю точку использования "do/while" и сделает
этот макрос в значительной степени эквивалентен версии составного оператора.
Я не знаю, почему автор кода, который вы цитировали в своем оригинале
сообщение ;
после while (0)
. В этой форме оба варианта:
эквивалент. Вся идея использования версии "do/while" заключается не в том, чтобы
включить этот окончательный ;
в макрос (по причинам, которые я объяснил
выше).