Да, это плохо. Используйте goto
.
#define fail_unless(x) do {if(!(x)) goto fail;} while (0)
int foo()
{
fail_unless( my_write(...) );
fail_unless( bar() );
return 0;
fail:
cleanup();
return -1;
}
Редактировать : если вы отрицаете голосование, потому что не понимаете, что там делает цикл while, вы должны были просто спросить. Это стандартная техника, позволяющая убедиться, что макрос C действует как отдельный оператор в любом контексте. Если ваш макрос расширяется до оператора if (например, макросы в другом ответе с голосованием), вы получаете неожиданные побочные эффекты, например:
#define DONT_DO_THIS(x) if (!x) { foo; }
if (a) DONT_DO_THIS(x)
else something_else();
Вы ожидаете, что что-то будет выполнено, когда !a
, но на самом деле макрос расширяется до:
if (a)
if (!x) { foo;}
else something_else();
И что-то выполняется, когда a && x
, а не когда !a
, как задумал программист.