Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
188 views
in Technique[技术] by (71.8m points)

c - Expand macro to no code: "do {} while (0)" or "while (0) {}"

In my code I use a macro that should generate a log entry or it should not according to some compilation flag:

#ifdef SOMETHING                                                                
    #define LOG(a)     printf ("%s", a)                                         
#else                                                                           
    #define LOG(a)     while (0) {}                                             
#endif

This code is working fine, but when I look in the Internet, I only see people using

#define LOG(a)     do {} while (0)

instead of

#define LOG(a)     while (0) {}

Are these two approaches equivalent? Should I prefer one over the other?

question from:https://stackoverflow.com/questions/65642472/expand-macro-to-no-code-do-while-0-or-while-0

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...