do while(0)的作用


閱讀Mitsuba的代碼的時候,發現了一個有意思的地方:

#define Log(level, fmt, ...) do { \
        mitsuba::Thread *thread = mitsuba::Thread::getThread(); \
        if (EXPECT_NOT_TAKEN(thread == NULL)) \
            throw std::runtime_error("Null thread pointer"); \
        mitsuba::Logger *logger = thread->getLogger(); \
        if (logger != NULL && level >= logger->getLogLevel()) \
            logger->log(level, m_theClass, \
                __FILE__, __LINE__, fmt, ## __VA_ARGS__); \
    } while (0)

定義了一個Log的宏函數,使用了do{...} while(0)的語法,這里的while中的條件是常量0,上面的代碼永遠只執行一遍。

感覺是多此一舉,做法令人費解。上stack overflow查了下資料。說法很多,我在下面歸納兩條比較有價值的分析:

1.就是上面的宏定義中,do{}while(0)的意義:

可以先看看Log宏函數如何被使用的:

Log(EInfo, "The time cost by init is %f",Time_stas::init_time);

Log別當作了一個函數來使用,所以,宏定義替換函數后,需要保證語義不會受到影響。

假設這樣的場景:

if( xxxx)

Log(xxx,"xxxxx");

else

xxxx;

如果我們不使用do{}while(0),使用{}把do{}中的語句括住。

上面的語句就成了:

if(xxxx)

{....};

else

就會出現編譯錯誤。

當然,使用

if(xxxx){

Log(xxx,xxx);

}else

{

}

可以避免上面使用{}的問題。但是,do{}while(0)的確為一種穩健的做法。

 

2.使用do{}while(0),可以使用break語句,從do中跳出,避免goto語句:

int test(int p)
{
  if(p==-1)
   {
       ...//do something
       goto smaecode;
    }  
   if(p ==0)
   {
     ...//do something
     goto smaecode;
   }
   if(p==1)
  {
      ...//do something
     goto smaecode;
  }
samecode:
     ...//do something
    
    return p;

}

在do{}while(0)內部使用break語句可以避免使用goto:

int test(int p)
{
do
{
  if(p == -1)
  {
    ..//do something 
    break;
  }
  if(p==0)
  {
    ..//do something
    break;
  }
  if(p == 1)
  {
    ..//do something
    break;
  }

}while(0);
...//same code
 return p ;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM