do {} while (0)
and while (0) {}
are not equivalent in all contexts, for example, in the latter case the user of the macro will naturally add a syntactically unnecessary semi-colon to the end so that:
if( error )
LOG( "ERROR") ;
else
{
...
}
would expand to:
if( error )
while(0){} ;
else
{
...
}
which fails by disassociating the else
from the if
because only the while(0){}
is conditional.
It should also be noted that neither are syntactically equivalent to the expression printf ("%s", a)
which has type int
and a better definition is either:
#ifdef SOMETHING
#define LOG(a) do{printf ("%s", a)} while(0)
#else
#define LOG(a) do{} while(0)
#endif
or
#ifdef SOMETHING
#define LOG(a) printf ("%s", a)
#else
#define LOG(a) 0
#endif
So that LOG()
can be used either wherever a statement is valid or wherever an expression is valid. The expression version should be used in circumstances where the value of the expression might be used. The expansion of the expression in a stand-alone statement :
0 ;
is a valid no-op or null statement, but some compilers or static analysers may issue a warning for unused expression.
Common no-op idioms such as :
#define LOG(a)
#define LOG(a) ((void)0)
might also be considered but all suffer from lack of syntactic equivalence to the alternate expansion in the sense that one expansion is valid in all the contexts that the other is valid.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…