C многострочный макрос:/в то время как (0) по сравнению с блоком объема [дубликат]

Моя копия C в двух словах раскрывает существование стандартной функции copysign, которая может быть полезна. Похоже, что copysign (1.0, -2.0) вернет -1.0, а copysign (1.0, 2.0) вернет +1.0.

Довольно близко, да?

173
задан Community 23 May 2017 в 12:18
поделиться

1 ответ

http://bytes.com/groups/c/219859-do- while-0-macro-substitutions

Андрей Тарасевич:

Сама идея использования 'do / в то время как 'версия заключается в создании макроса, который будет развернуть в обычный оператор, а не в составной оператор. Это сделано для того, чтобы использовать макросы функционального стиля, единообразные с использование обычных функций во всех контекстах.

Рассмотрим следующий набросок кода

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);

будет компилироваться без каких-либо проблем.

Однако обратите внимание на небольшое, но важное различие между моим определением of CALL_FUNCS и первая версия в вашем сообщении. Я не ставил ; после }, а (0) . Помещая ; в конце этого определения немедленно уничтожит весь смысл использования 'do / while' и сделает этот макрос в значительной степени эквивалентен версии составного оператора.

Я не знаю, почему автор кода, который вы цитировали в своем оригинале сообщение поместите это ; после , а (0) . В этой форме оба варианта эквивалент. Вся идея использования версии do / while заключается не в том, чтобы включите этот последний ; в макрос (по причинам, которые я объяснил выше).

258
ответ дан 23 November 2019 в 20:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: