第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機(jī)立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么在宏中使用明顯無意義的do-while和if-else語句?

為什么在宏中使用明顯無意義的do-while和if-else語句?

C C++
慕妹3242003 2019-05-27 13:52:32
為什么在宏中使用明顯無意義的do-while和if-else語句?在許多C / C ++宏中,我看到宏的代碼包含在看似無意義的do while循環(huán)中。這是一些例子。#define FOO(X) do { f(X); g(X); } while (0) #define FOO(X) if (1) { f(X); g(X); } else我看不出它do while在做什么。為什么不在沒有它的情況下寫這個?#define FOO(X) f(X); g(X)
查看完整描述

4 回答

?
胡說叔叔

TA貢獻(xiàn)1804條經(jīng)驗 獲得超8個贊

do ... whileif ... else在那里讓這個后您的宏分號總是意味著同樣的事情。假設(shè)你有類似第二個宏的東西。

#define BAR(X) f(x); g(x)

現(xiàn)在,如果你要BAR(X);在一個if ... else語句中使用if語句的主體沒有用大括號括起來,你會得到一個不好的驚喜。

if (corge)
  BAR(corge);else
  gralt();

上面的代碼將擴(kuò)展為

if (corge)
  f(corge); g(corge);else
  gralt();

這在語法上是不正確的,因為else不再與if相關(guān)聯(lián)。在宏中用大括號括起來是沒有用的,因為大括號后面的分號在語法上是不正確的。

if (corge)
  {f(corge); g(corge);};else
  gralt();

有兩種方法可以解決問題。第一種方法是使用逗號對宏中的語句進(jìn)行排序,而不會使其具有像表達(dá)式一樣的能力。

#define BAR(X) f(X), g(X)

上面的bar版本BAR將上面的代碼擴(kuò)展為以下代碼,這在語法上是正確的。

if (corge)
  f(corge), g(corge);else
  gralt();

如果不是f(X)你有一個更復(fù)雜的代碼體,需要進(jìn)入它自己的塊,比如聲明局部變量,這就行不通了。在最一般的情況下,解決方案是使用類似的東西do ... while使宏成為一個單獨的語句,分號不會混淆。

#define BAR(X) do { \  int i = f(X); \  if (i > 4) g(i); \} while (0)

你不必使用do ... while,你也可以做一些東西if ... else,雖然當(dāng)它if ... else內(nèi)部擴(kuò)展時會if ... else導(dǎo)致“ 懸掛其他 ”,這可能使現(xiàn)有懸掛的其他問題更難找到,如下面的代碼。

if (corge)
  if (1) { f(corge); g(corge); } else;else
  gralt();

關(guān)鍵是在懸掛分號錯誤的情況下用掉分號。當(dāng)然,在這一點上它可能(并且可能應(yīng)該)被認(rèn)為最好將其聲明BAR為實際函數(shù),而不是宏。

總之,do ... while可以解決C預(yù)處理器的缺點。當(dāng)那些C風(fēng)格指南告訴你裁掉C預(yù)處理器時,這是他們擔(dān)心的事情。


查看完整回答
反對 回復(fù) 2019-05-27
?
四季花海

TA貢獻(xiàn)1811條經(jīng)驗 獲得超5個贊

宏是復(fù)制/粘貼的文本,預(yù)處理器將放入正版代碼中; 宏的作者希望替換產(chǎn)生有效的代碼。

有三個好的“提示”可以成功:

幫助宏的行為像真正的代碼

正常代碼通常以分號結(jié)束。如果用戶查看不需要的代碼......

doSomething(1) ;DO_SOMETHING_ELSE(2)  // <== Hey? What's this?doSomethingElseAgain(3) ;

這意味著如果沒有分號,用戶希望編譯器產(chǎn)生錯誤。

但真正正確的理由是,在某些時候,宏的作者可能需要用真正的函數(shù)(也許是內(nèi)聯(lián)函數(shù))替換宏。所以宏應(yīng)該真的像一個。

所以我們應(yīng)該有一個需要分號的宏。

生成有效的代碼

如jfm3的答案所示,有時宏包含多條指令。如果宏在if語句中使用,這將是有問題的:

if(bIsOk)
   MY_MACRO(42) ;

此宏可以擴(kuò)展為:

#define MY_MACRO(x) f(x) ; g(x)if(bIsOk)
   f(42) ; g(42) ; // was MY_MACRO(42) ;

g無論值如何,都將執(zhí)行該功能bIsOk。

這意味著我們必須向宏添加一個范圍:

#define MY_MACRO(x) { f(x) ; g(x) ; }if(bIsOk)
   { f(42) ; g(42) ; } ; // was MY_MACRO(42) ;

生成有效的代碼2

如果宏是這樣的:

#define MY_MACRO(x) int i = x + 1 ; f(i) ;

我們可能在以下代碼中遇到另一個問題:

void doSomething(){
    int i = 25 ;
    MY_MACRO(32) ;}

因為它會擴(kuò)展為:

void doSomething(){
    int i = 25 ;
    int i = 32 + 1 ; f(i) ; ; // was MY_MACRO(32) ;}

當(dāng)然,這段代碼不會編譯。所以,再一次,解決方案是使用范圍:

#define MY_MACRO(x) { int i = x + 1 ; f(i) ; }void doSomething(){
    int i = 25 ;
    { int i = 32 + 1 ; f(i) ; } ; // was MY_MACRO(32) ;}

代碼再次正常運行。

結(jié)合分號+范圍效應(yīng)?

有一個產(chǎn)生這種效果的C / C ++習(xí)語:do / while循環(huán):

do{
    // code}while(false) ;

do / while可以創(chuàng)建一個范圍,從而封裝宏的代碼,最后需要一個分號,從而擴(kuò)展為需要一個代碼的代碼。

獎金?

C ++編譯器將優(yōu)化do / while循環(huán),因為其后置條件為false的事實在編譯時是已知的。這意味著像一個宏:

#define MY_MACRO(x)                                  \do                                                  
 \{                                                    \    const int i = x + 1 ;                            
 \
    f(i) ; g(i) ;                                    \}                                                    
    \while(false)void doSomething(bool bIsOk){
   int i = 25 ;

   if(bIsOk)
      MY_MACRO(42) ;

   // Etc.}

將正確擴(kuò)展為

void doSomething(bool bIsOk){
   int i = 25 ;

   if(bIsOk)
      do
      {
         const int i = 42 + 1 ; // was MY_MACRO(42) ;
         f(i) ; g(i) ;
      }
      while(false) ;

   // Etc.}

然后編譯和優(yōu)化

void doSomething(bool bIsOk){
   int i = 25 ;

   if(bIsOk)
   {
      f(43) ; g(43) ;
   }

   // Etc.}


查看完整回答
反對 回復(fù) 2019-05-27
?
月關(guān)寶盒

TA貢獻(xiàn)1772條經(jīng)驗 獲得超5個贊

您可能還想補(bǔ)充一點,宏語法也可以使用簡單的“if”語句防止可能更危險(因為沒有錯誤)的意外行為:

#define FOO(x)  f(x); g(x)if (test) FOO( baz);

擴(kuò)展為:

if (test) f(baz); g(baz);

這在語法上是正確的,所以沒有編譯器錯誤,但可能有意外的結(jié)果,g()將始終被調(diào)用。


查看完整回答
反對 回復(fù) 2019-05-27
?
長風(fēng)秋雁

TA貢獻(xiàn)1757條經(jīng)驗 獲得超7個贊

上述答案解釋了這些結(jié)構(gòu)的含義,但兩者之間存在顯著差異,未提及。其實,還有一個原因,更喜歡do ... whileif ... else結(jié)構(gòu)。

if ... else構(gòu)造的問題是它不會強(qiáng)迫你輸出分號。喜歡這段代碼:

FOO(1)printf("abc");

雖然我們遺漏了分號(錯誤地),但代碼將擴(kuò)展為

if (1) { f(X); g(X); } elseprintf("abc");

并將靜默編譯(雖然一些編譯器可能會發(fā)出無法訪問代碼的警告)。但該printf聲明永遠(yuǎn)不會被執(zhí)行。

do ... while構(gòu)造沒有這樣的問題,因為之后唯一有效的標(biāo)記while(0)是分號。


查看完整回答
反對 回復(fù) 2019-05-27
  • 4 回答
  • 0 關(guān)注
  • 870 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號