do{...}while(0)用法总结

1、消除冗余代码以及避免微妙的goto语句:

通常,如果一个函数开始要分配一些资源,然后如果在中途遇到错误则要退出函数,当然,退出前要释放资源

一般写法:

 1 int InitSomething()
 2 {
 3     char* pImage = NULL;
 4     char* pBitMap = NULL;
 5     char* pBuffer = NULL;
 6 
 7     pImage = (char*)malloc(10);
 8     if(pImage == NULL)
 9     {
10         return -1;
11     }
12 
13     pBitMap = (char*)malloc(20);
14     if (NULL == pBitMap)
15     {
16         free(pImage);
17         return -1;
18     }
19     
20     pBuffer = (char*)malloc(1024);
21     if(NULL == pBuffer)
22     {
23         free(pImage);
24         free(pBitMap);
25         return -1;
26     }
27 
28     ....
29 
30 
31     free(pImage);
32     free(pBitMap);
33     free(pBuffer);
34 
35     return 0;
36 }
View Code

goto语句写法:

 1 int InitSomething()
 2 {
 3     char* pImage = NULL;
 4     char* pBitMap = NULL;
 5     char* pBuffer = NULL;
 6 
 7     pImage = (char*)malloc(10);
 8     if(pImage == NULL)
 9     {
10         goto ret;
11     }
12 
13     pBitMap = (char*)malloc(20);
14     if (NULL == pBitMap)
15     {
16         goto ret;
17     }
18     
19     pBuffer = (char*)malloc(1024);
20     if(NULL == pBuffer)
21     {
22         goto ret;
23     }
24 
25     ....
26 
27     return 0;
28 ret:
29     if (pImage)
30     {
31         free(pImage);
32     }
33 
34     if (pBitMap)
35     {
36         free(pBitMap);
37     }
38 
39     if (pBuffer)
40     {
41         free(pBuffer);
42     }
43 
44     return -1;
45 }
View Code

do...while(0)优化写法:

 1 int InitSomething()
 2 {
 3     char* pImage = NULL;
 4     char* pBitMap = NULL;
 5     char* pBuffer = NULL;
 6     int nRet = 0;
 7 
 8     do
 9     {
10         pImage = (char*)malloc(10);
11         if(pImage == NULL)
12         {
13             nRet = -1;
14             break;
15         }
16 
17         pBitMap = (char*)malloc(20);
18         if (NULL == pBitMap)
19         {
20             nRet = -1;
21             break;
22         }
23         
24         pBuffer = (char*)malloc(1024);
25         if(NULL == pBuffer)
26         {
27             nRet = -1;
28             break;
29         }
30     }while(0);
31 
32     if (nRet != 0)
33     {
34         if (pImage)
35         {
36             free(pImage);
37         }
38 
39         if (pBitMap)
40         {
41             free(pBitMap);
42         }
43 
44         if (pBuffer)
45         {
46             free(pBuffer);
47         }
48         return -1;
49     }
50 
51     ....
52 
53     return 0;
54 }
View Code

2、消除空声明在编译时出现警告:

#define FOOBAR do { } while(0)

3、消除代码块误用而产生的编译或运行时的错误:

#define swap(x,y) { int tmp; tmp=x; x=y; y=tmp; }

if (x > y)
    swap(x,y);
else  
    dosth();
编译后预处理器替换的代码如下:
if (x > y)
    { int tmp; tmp=x; x=y; y=tmp; };
else//变成了悬空分支
    do_something();

错误出在分号“;”直接位于代码块的后面,解决的办法:宏定义嵌到do...while(0):
#define swap(x,y) do { int tmp; tmp=x; x=y; y=tmp; } while(0)

宏展开后的代码如下:
if (x > y)
    do { int tmp; tmp=x; x=y; y=tmp; } while(0);
else
    do_something();

4、消除条件语句中使用宏的隐患:

#define FOOBAR(x) \
    printf("parameter is %s\n", x); \
    do_sth(x)

如下代码片段
if (name == 2)
    FOOBAR("tcp");

宏展开后:
if (name == 2)
    printf("parameter is %s\n", "tcp");do_sth("tcp");

但实际上:if语句只作用于printf(), do_sth() 没按照原有意图一起受到条件的控制

重新定义宏:
#define FOOBAR(x) \
do{ \
    printf("parameter is %s\n", x); \
    do_sth(x);\
}while(0)

代码片段展开:
if (name == 2)
    do{printf("arg is %s\n", "tcp"); do_sth("tcp");} while (0);

 

posted on 2014-07-03 16:32  eric.geoffrey  阅读(461)  评论(0编辑  收藏  举报

导航