Подтвердить что ты не робот

Зачем использовать {} 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

4b9b3361

Ответ 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).