Несколько объяснений. Первый - общий, второй - специфичный для макросов препроцессора C с параметрами:
Управление потоком
Я видел, как это использовалось в простом коде C. По сути, это более безопасная версия goto, так как вы можете выйти из нее, и вся память будет очищена должным образом.
Почему что-то вроде gotoдолжно быть хорошим? Что ж, если у вас есть код, в котором практически каждая строка может возвращать ошибку, но вам нужно реагировать на все из них одинаково (например, передавая ошибку вызывающему абоненту после очистки), это обычно более читабельно, чтобы избежать if( error ) { /* cleanup and error string generation and return here */ }as это позволяет избежать дублирования кода очистки.
Однако в C ++ есть исключения + RAII именно для этой цели, поэтому я считаю это плохим стилем кодирования.
Проверка точки с запятой
Если вы забудете точку с запятой после вызова макроса, подобного функции, аргументы могут нежелательным образом сжиматься и компилироваться в допустимый синтаксис. Представьте себе макрос
#define PRINT_IF_DEBUGMODE_ON(msg) if( gDebugModeOn ) printf("foo");
Это случайно называется
if( foo )
PRINT_IF_DEBUGMODE_ON("Hullo\n")
else
doSomethingElse();
«Еще» будет считаться ассоциироваться с gDebugModeOn, так что, когда fooэтоfalse произойдет, произойдет полная противоположность того, что было задумано.
Предоставление области для временных переменных.
Поскольку do / while имеет фигурные скобки, временные переменные имеют четко определенную область видимости, из которой они не могут выйти.
Как избежать предупреждений о потенциально нежелательных точках с запятой
Некоторые макросы активируются только в отладочных сборках. Вы определяете их как:
#if DEBUG
#define DBG_PRINT_NUM(n) printf("%d\n",n);
#else
#define DBG_PRINT_NUM(n)
#endif
Теперь, если вы используете это в сборке выпуска внутри условного оператора, он компилируется в
if( foo )
;
Многие компиляторы видят в этом то же, что и
if( foo );
Что часто пишется случайно. Итак, вы получите предупреждение. Do {} while (false) скрывает это от компилятора и принимается им как признак того, что вы действительно хотите здесь ничего делать.
Как избежать захвата строк условными операторами
Макрос из предыдущего примера:
if( foo )
DBG_PRINT_NUM(42)
doSomething();
Теперь, в отладочной сборке, поскольку мы обычно включаем точку с запятой, это компилируется нормально. Однако в сборке релиза это внезапно превращается в:
if( foo )
doSomething();
Или более четко отформатированный
if( foo )
doSomething();
Это совсем не то, что было задумано. Добавление do {...} while (false) вокруг макроса превращает отсутствующую точку с запятой в ошибку компиляции.
Что это значит для ОП?
В общем, вы хотите использовать исключения в C ++ для обработки ошибок и шаблоны вместо макросов. Однако в очень редких случаях, когда вам все еще нужны макросы (например, при генерации имен классов с помощью вставки токенов) или вы ограничены простым C, это полезный шаблон.