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
GNU的C扩展({})的用法

 


posted on 2014-08-07 11:24  杰瑞鼠  阅读(503)  评论(0)    收藏  举报