C语言-define 与do{}while(0)
问题引出:
我们都知道宏定义#define只是简单替换,所以遇到复杂的带参数宏,必须很小心的为需要的参数加上括号“()”;同样碰到复杂的多条语句替代,虽然加{}可以将其封装成一个整体,但同时又有另一个问题:与语法习惯的冲突。比如:
#include <stdio.h>
void print_1(void)
{
printf("print_1\n");
}
void print_2(void)
{
printf("print_2\n");
}
#define printf_value() \
{ \
print_1(); \
print_2();
}
int main( void )
{
int i=0;
if(i==1)
else
printf("add else word!!!");printf_value();
return 0;
}
上面的经过编译后会报错:if与else不匹配。怎么可能?将宏带入发现“printf_value();”后面确实多了一个分号,从而导致if与else的不匹配。但是去掉又不和c语言的习惯,因为C规定每条语句后面必须加分号。
所以解决的办法就是用do{}while(0)同样只执行一次,且将其看成一个整体,且可以提前退出,同时又兼容了C的习惯,一举多得。但缺点是不能作为返回值和函数右值。此时用GNU对c语言的扩展({})可以解决右值和返回值,但不能中途退出,之所以如此神奇是因为规定({}) 中的最后一条语句的结果为该双括号体的返回值 ,即下述例子中ret作为了函数宏的返回值。参考《C语言函数这样封装,会提高你的编程档次》
1 #define INT_SWAP(a,b) \ 2 ({ \ 3 int ret = 0; \ 4 if (a < 0 || b < 0) \ 5 { \ 6 ret = -1; \ 7 } \ 8 else \ 9 { \ 10 int tmp = a; \ 11 a = b; \ 12 b = tmp; \ 13 } \ 14 ret; \ 15 }) 16 17 int main() 18 { 19 int var_a = 1; 20 int var_b = 2; 21 22 if (INT_SWAP(var_a, var_b) != -1) 23 printf("swap success !!\n"); // swap success !! 24 else 25 printf("swap fail !!\n"); 26 printf("var_a = %d, var_b = %d\n", var_a, var_b); // var_a = 2, var_b = 1
浙公网安备 33010602011771号