2009-06-10 256 views
0

考慮這款C結構,這樣做實際工作前檢查錯誤使用C開關語句?使用goto或堆疊if()的替代品會更好嗎?錯誤處理

+0

我真的不害怕gotos ...我對這個構造很嚴格,希望得到一些反饋。 – 0x6adb015 2009-06-10 13:12:19

回答

5

我從來沒有見過的開關解決方案,但我已經做了這樣的東西:

do { 
    err = func(); 
    if(err) break; 
    err = func2(); 
    if(err) break; 
    ... 
} while(0); 
if(err) { 
    // handle errors 
} 

但是那是什麼,這之間的真正區別:

err = func(); 
if(err) goto done; 
err = func2(); 
if(err) goto done; 
... 
done: 
if(err) { 
    //handle errors; 
} 

第一隻是第二個重寫,以避免使用關鍵字goto,而且我認爲,goto溶液更具有可讀性。我花了一段時間,但我設法說服自己,goto s不是總是邪惡。最後,如果可能,我寧願只使用if語句,因爲它使代碼更具可讀性,但goto(如有必要)。

4

我會說這是可讀性較差。我認爲使用if語句或甚至是goto會是更合適的方法。使用goto's不是世界末日,完全可以接受並且適合錯誤處理。

http://kerneltrap.org/node/553/2131

+0

我同意,如果有人看到那個switch(),它需要一些時間來破譯它的功能。 – 0x6adb015 2009-06-10 13:13:00

0

我會建議你使用,而(真)代替開關:

while(true) 
{ 
      retval = BUFFER_INACTIVE; 
      if(conn->mSocket == -1) 
        break; 
      retval = BUFFER_FULL; 
      /* Is there enough room to add ? */ 
      if((context->mMaxBufferSize - conn->mSendPacketLength) < aPacketLength) 
        break; 

      /* Is the send packet buffer half sent? */ 
      if(conn->mSendPacketLength > 0 && conn->mSendPacketPos != conn->mSendPacket) 
        break; 

      /* Do some work here */ 
      retval = BUFFER_DONE; 
      break; 
} 
+1

我認爲while(true)會導致某人期望循環,這絕對不會。使用「do {...} while(0);」比較習慣。 – 2009-06-10 14:33:33

+0

同意,做{...} while(0);是更好的方法來做到這一點。 – 2009-06-10 15:07:55

0

另一種替代方法是將其封裝在函數中並返回而不是中斷。這通常是一個壞主意,因爲它最終會增加一個不必要的抽象層。但是,在某些情況下,它可以使事情變得更簡單。

-1

另一種方法是使用級聯IFS:

u8 u8IsOk; 

u8IsOk = Func1(); 

if(u8IsOk) 
{ 
    /* Do some stuff...*/ 
    u8IsOk = Func2(); 
} /* if */ 

if(u8IsOk) 
{ 
    /* Do some stuff...*/ 
    u8IsOk = Func3(); 
} /* if */ 

...等等。沒有其他方法那樣高效,但避免了過多的嵌套,goto,break,while(0)和多個返回。