Многострочный макрос C:do/ while(0) против блока области [дубликат]
Вопрос
Возможные дубликаты:
Какая польза от do while(0), когда мы определяем макрос?
Почему в макросах C/C++ иногда встречаются бессмысленные операторы do/ while и if/else?
do { … } while (0) для чего это нужно?
Я видел несколько многострочных макросов C, заключенных в цикл do/ while(0), например:
#define FOO \ do { \ do_stuff_here \ do_more_stuff \ } while (0)
Каковы преимущества (если таковые имеются) от написания кода таким образом по сравнению с использованием базового блока:
#define FOO \ { \ do_stuff_here \ do_more_stuff \ }
Решение
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);
Теперь, если ваш макрос определяется в соответствии со вторым подходом (Just '{' 'и'} '), код больше не будет компилироваться, потому что «истинная» ветвь «if» теперь представлена составным оператором.И когда вы ставите ';' После этого составного оператора вы завершили целое оператор «if», таким образом, отировывая ветвь «Истоте» (отсюда и ошибка компиляции).
Один из способов исправить эту проблему - помнить, что не ставят «»; После макро "призывных"
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' не в том, чтобы
включите этот финал ;
в макрос (по причинам, которые я объяснил
выше).