现在的位置: 首页 > 综合 > 正文

宏定义里的 do{} while (0)以及我的认识

2013年12月05日 ⁄ 综合 ⁄ 共 1252字 ⁄ 字号 评论关闭

无论是Linux内核还是其他著名的c、c++库里都能见到 do{} while (0)

这样的写法看似没有意义,其实出自名家之手,是在宏定义里使用的

以前就了解到在程序里使用宏定义的函数后面的分号容易导致问题,今天算是深入认识了

先看一个简单的宏

#define SAFE_FREE(p) do {free(p);p=NULL;} while(0)

如果去掉了do... while(0)

即定义SAFE_FREE(p)为

#define SAFE_FREE(p)   free(p);p=NULL;

那么下面的代码

if(NULL!=p)

    SAFE_FREE(p)

else

//do something

将被展开为:

if(NULL!=p)

    free(p);p=NULL;

else

//do something

这样就导致if后面有两条语句,第二条语句总会执行,且else不再与原来的if匹配

 

所以一般聪明的人在定义宏函数的时候会加上 {}

#define SAFE_FREE(p)   { free(p);p=NULL;}

这样貌似解决了问题,可是还是有隐患

因为很多人习惯在C代码最后都加 ;

没有经验的人往往会不管那个SAFE_FREE(p)全是大写,直接在后面加上;

if(NULL!=p)

    SAFE_FREE(p);

else

//do something

被展开为

if(NULL!=p)

   { free(p);p=NULL;};

else

//do something

 

这样 仍然导致if和else的匹配被破坏的情况

 

如果使用名家的方法

#define SAFE_FREE(p) do {free(p);p=NULL;} while(0)

那么

if(NULL!=p)

    SAFE_FREE(p);

else

//do something

展开为

if(NULL!=p)

do

   { free(p);p=NULL;}

while(0);

else

//do something

好了 这样就一切太平了

 

书上是这么说,可是我认为虽然采用了

#define SAFE_FREE(p) do {free(p);p=NULL;} while(0) 这样的定义

可是使用者要是突然意识到SAFE_FREE(p)是个宏,然后自作聪明没有在SAFE_FREE(p)后加;

if(NULL!=p)

    SAFE_FREE(p)

else

//do something

这样展开

if(NULL!=p)

do

   { free(p);p=NULL;};

while(0)

else

//do something

这样while(0)后面没有; 仍然报错!

 

聪明反被聪明误,只因为还不够聪明。

解决问题最简单的方法就是良好的编程习惯

一个没有任何问题的if else结构就能解决所有的问题

if(NULL!=P)

    {//do something }

else

    { //do something   }

就是两点,NULL!=P而不是p!=NULL ,还有就是齐全的{}匹配

说来容易,但是我们在网上甚至是名著里仍然很难看到完美的写法

 

不要偷懒,少打那么几个{},否则会付出更惨痛的代价

抱歉!评论已关闭.