将宏扩展为无代码:“do{}while(0)”或“while(0){}”

在我的代码中,我使用了一个宏,它应该生成一个日志条目,或者它不应该根据一些编译标志:

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

这段代码运行良好,但是当我查看 Internet 时,我只看到有人在使用

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

代替

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

这两种方法等价吗?我应该更喜欢一个吗?

回答

do {} while (0)并且while (0) {}在所有上下文中都不是等价的,例如,在后一种情况下,宏的用户自然会在末尾添加一个语法上不必要的分号,以便:

if( error )
    LOG( "ERROR") ;
else
{
    ...
}

将扩展为:

if( error )
    while(0){} ;
else
{
    ...
}

由于只有 the是有条件的elseif因此将 the与 the分离而失败while(0){}

还应该注意的是,两者在语法上都不等同于具有类型的表达式 printf ("%s", a)int更好的定义是:

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

或者

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

因此,它LOG()可以在任何语句有效或表达式有效的地方使用。该表达的版本应该在可能被使用的表达式的值情况下使用。独立语句中表达式的扩展:

0 ;

是有效的 no-op 或 null 语句,但某些编译器或静态分析器可能会针对未使用的表达式发出警告。

常见的无操作习语,例如:

#define LOG(a)
#define LOG(a) ((void)0)

也可以考虑,但都缺乏与替代扩展的句法等效,因为一个扩展在另一个有效的所有上下文中都有效。


回答

他们的不同之处在于

do {} while (0)

语句末尾需要一个分号,而

while (0) {}

才不是。

所以,当你写

LOG ("Some textn");

第一个它扩展到

do {} while (0);

这是一个单一的语句,但第二个它扩展到

while (0) {};

这是两个陈述,thewhile (0) {}和 the ;(这是一个有效的陈述)。

当您将它与if. 我你写的东西是这样的:

if (1)
    LOG ("Condition is truen");
else
    LOG ("Condition is falsen");

通过这种while (0) {}方法,这扩展到

if (1)
    while (0) {};
else
    while (0) {};

这相当于

if (1)
    while (0) {}
;
else
    while (0) {}
;

这不会编译,因为有一个else没有相应的if.

因此,您应该更喜欢这种do {} while (0)方法以获得更大的兼容性。此外,它更地道。


以上是将宏扩展为无代码:“do{}while(0)”或“while(0){}”的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>