2011-03-18 60 views
1

可能重复:
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?为什么在宏中使用'do {} while(0)'?

在我的C代码,我需要使用宏。我使用gcc编译我的代码。 下面是我的实验:

#define temp(a, b) a++; \ 
    b++; 

foo() 
{ 
    temp(x, y); 
} 

^^^^^ this will work fine 

#define temp(a, b) a++; \ 
    b++; 

foo() 
{ 
    if(z) 
    temp(x, y); 
    else 
    foo(); 
} 

^^^^^ this will not work 

#define temp(a, b) { \          <<< 
    a++; \ 
    b++; \ 
    }          <<< 

foo() 
{ 
    if(z) 
    temp(x, y); 
    else 
    foo(); 
} 

^^^^^ this will also not work 

#define temp(a, b) do { \          <<< 
    a++; \ 
    b++; \ 
    } while(0)         <<< 

foo() 
{ 
    if(z) 
    temp(x, y); 
    else 
    foo(); 
} 

^^^^^ this will work :) 

回答

2

“作而”可以作为一个语句,并用终止它,它是适当的;这是你在使用temp之后写的。

其他示例不起作用,因为当扩展宏时,生成的代码具有不正确的C++语法,或者不代表您希望它的含义。

#define temp(a, b) a++; \ 
    b++; 

foo() 
{ 
    if(z) 
    temp(x, y); 
    else 
    foo(); 
} 

不起作用,因为它扩展为:如果

foo() 
{ 
    if(z) 
    x++; 
    b++; 
    else 
    foo(); 
} 

的身体或者只允许为一个语句在C++中,但你基本上是放两个。

#define temp(a, b) { \ 
    a++; \ 
    b++; \ 
    } 

foo() 
{ 
    if(z) 
    temp(x, y); 
    else 
    foo(); 
} 

扩展为:

foo() 
{ 
    if(z) 
    { 
    a++; 
    b++; 
    }; 
    else 
    foo(); 
} 

分号;在语言规则不允许的情况下,我得到编译错误“非法其他没有匹配,如果”

但'do-while'版本确实工作。它扩展为:

foo() 
{ 
    if(z) 
    do { 
     a++; 
     b++; 
    } while(0); 
    else 
    foo(); 
} 

这是完全合法的C++并具有您想要的行为。 do-while的主体将被执行一次,并且0被视为false并导致执行离开循环。编译器应该能够认识到while条件始终是错误的,并且会生成有效运行的机器指令。

+1

顺便说一句,我一般喜欢有功能十岁上下的宏扩展为右值,而不是报表时实际(比如'的#define FOO() (a ++,b ++)'),因为实数函数调用可以包含在rvalues中,但语句不能。 – supercat 2012-06-13 19:38:12