Зачем использовать {} while (0) в определении макроса?
Возможный дубликат:
Почему иногда существуют бессмысленные операторы do/while и if/else в макросах C/С++?
Я встретил код, как показано ниже:
#define ev_io_init(ev,cb,fd,events) \
do { \
ev_init ((ev), (cb)); \
ev_io_set ((ev),(fd),(events)); \
} while (0)
Я хочу знать, почему автор использует do { } while (0)
здесь.
Есть ли разница с этим?
#define ev_io_init(ev,cb,fd,events) { \
ev_init ((ev), (cb)); \
ev_io_set ((ev),(fd),(events)); \
}
BTW: код из libev, ev_local.h
Ответы
Ответ 1
Рассмотрим if( something ) function1(); else function2();
Если function1()
на самом деле является макросом, просто используя { }
, вы должны опустить точку с запятой в точке использования, но do { } while(0)
позволяет использовать точно такой же синтаксис, как и для реальной функции.
(Не используя какой-либо блок-конструкции вообще, просто сгенерировал бы полностью сломанный код, natch)
Ответ 2
Кодирующий код с циклом позволяет директиве препроцессора выполнять несколько операторов без "взлома" if-else-конструкций. Рассмотрим следующее:
#define DO_SOMETHING() a();b();c();
void foo()
{
// This is ok...
DO_SOMETHING();
}
void bar()
{
// ...whereas this would trigger an error.
if (condition)
DO_SOMETHING();
else
blah();
}
Второй пример разбивает конструкцию if-else, потому что за тремя операторами следует предложение else
. Чтобы его правильно заменить, инструкции в DO_SOMETHING
должны быть заключены в do { ... } while(0)
.
Ответ 3
A do{}while(0)
позволяет вам выйти из цикла:
do{
expr1;
foo();
if ( cond )
break;
expr2;
goo();
} while (0);
Это то же самое, что и простой блок {...}
, за исключением того, что вы можете разорвать выполнение, если хотите, с помощью инструкции break
. Вы не могли бы сделать это в простом блоке кода, если у вас не было нескольких проверок, которые могут стать громоздкими. Он по-прежнему выполняется один раз из-за условия while(0)
.