经常出现在宏定义中的do { } while(0)循环

  C/C++ 经常用到的有三种循环,for,while,do while,其实,在平常编写代码的过程中,前两者是经常用到的,一个是知道循环的次数的情况下,第二种是未知循环次数的情况下,那么第三种循环在哪里经常看到呢,在宏定义中。
  现在我们要定义一个宏,去执行两个函数。

 1 void printf1()
 2 {
 3         printf("Function printf1\n");
 4 }
 5 
 6 void printf2()
 7 {
 8         printf("Function printf2\n");
 9 }
10 
11 #define printf_func() \
12                     printf1(); \
13                     printf2();    
14 int main()
15 {
16      printf_func();
17      
18      return 0;      
19 }

但是当我们在执行宏printf_func()的时候,要是有了条件限制如下(宏定义和函数见上)

int main()
{
    int flag = 0;
    if ( flag == 1 )
        printf_func();
     
    return 0;      
}

这样运行得到的结果:,本来我们是想要是if条件不满足的话,应该是printf_func()应该不会被执行的,将代码进行替换之后就会发现,if仅仅能限制到printf1(),而printf2()在控制之外导致的。那么怎么能避免这种错误的结果,不妨加一个{}试试。

void printf1()
{
        printf("Function printf1\n");
}

void printf2()
{
       printf("Function printf2\n");
}

#define printf_func() \
                    { \
                      printf1(); \
                      printf2();\
                     }    
 int main()
{
    int flag = 0;
    if ( flag == 1 )
       printf_func();
      
    return 0;      
}

这样运行代码之后,确实可以避免上面的情况产生,但是又会引入另一个问题,当这里的if语句有了else分支的时候就会有问题。

int main()
{
    int flag = 0;
    if ( flag == 1 )
        printf_func();
    else
        printf(" flag = 0\n"); 
    return 0;      
}

这样我们去编译的时候会报错 error C2181: 没有匹配 if 的非法 else ,仔细看代码分析就会发现printf_func()后面的分号导致的,于是尝试使用do{}while(0) 循环结构把宏包裹起来,成为一个独立的语法单元,从而不会与上下文发生混淆。同时由于绝大多数的编译器都能够识别do{}while(0)这种无用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低。

void printf1()
{
    printf("Function printf1\n");
}

void printf2()
{
    printf("Function printf2\n");
}

#define printf_func() \
               do { \
                    printf1(); \
                    printf2();\
                   }while (0)    

int main()
{
    int flag = 0;

    if ( flag == 1 )
        printf_func();
    else
        printf(" flag = 0\n"); 

    return 0;      
}        

这样就没有问题了,而且在循环中,由于while括号中的条件是 0 ,只会被执行一次。

posted on 2013-11-24 00:32  Green Time  阅读(731)  评论(0)    收藏  举报