Моя копия C в двух словах раскрывает существование стандартной функции copysign, которая может быть полезна. Похоже, что copysign (1.0, -2.0) вернет -1.0, а copysign (1.0, 2.0) вернет +1.0.
Довольно близко, да?
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 заключается не в том, чтобы
включите этот последний ;
в макрос (по причинам, которые я объяснил
выше).