Многострочный макрос C:do/ while(0) против блока области [дубликат]

StackOverflow https://stackoverflow.com/questions/1067226

  •  21-08-2019
  •  | 
  •  

Вопрос

Возможные дубликаты:
Какая польза от 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' не в том, чтобы включите этот финал ; в макрос (по причинам, которые я объяснил выше).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top