作者Schottky (順風相送)
看板C_and_CPP
標題Re: [問題] return問題
時間Thu Apr 28 15:23:32 2016
※ 引述《david830317 (dd810)》之銘言:
: 開發平台(Platform): (Ex: VC++, GCC, Linux, ...)
: Xcode
: 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
: 問題(Question):
: 在xcode時用void以外不能用reture
: 錯誤結果(Wrong Output):
: Control may reach end of non-void function
: 程式碼(Code):(請善用置底文網頁, 記得排版)
: http://ideone.com/T36LJH
: 補充說明(Supplement):
關於這個 function 的寫法
float Quantity::calcValue() const
{
if (unit >= 1 && unit <= 10)
{
return unit * 3.00;
}
if (unit >= 11 && unit <= 50)
{
return unit * 2.50;
}
if (unit >= 51)
{
return unit * 2.00;
}
}
我比較建議用 if-elseif-elseif 的結構來寫:
float Quantity::calcValue() const
{
if (unit >= 1.0f && unit <= 10.0f) {
return unit * 3.00f;
} else if (unit > 1.0f && unit <= 50.0f) {
return unit * 2.50f;
} else if (unit >= 50.0f) {
return unit * 2.00f;
} else {
/* default */
return unit;
}
/* Unreached */
}
原因:
1. 這樣才看得清楚這三條 if 其實是負責同一件事,條件排列整齊後,漏網之魚也
在 default 那一區塊有處理,不管是 error handling 還是 return default,
而且所有的狀況在 if-else 結構內都會 return,能輕易判斷函式終結點。
2. float 運算時,不管是比大小還是運算,最好兩邊都是 float (10.0f),
你有些寫 int,問題倒還不大反正會轉成 float,但有些寫 double (2.50) 就
會兩邊都轉成 double 運算,運算完再轉 float 再 return,浪費效能。
另一個問題點,你大概一開始把 unit 定義為 int 後來才改 float,
所以 if 裡面完全沒有處理到 10.0f<unit<11.0f, 50.0f<unit<51.0f 的狀況,
如果習慣把常數的 data type 也寫對,遇到可能有問題的狀況,心中自然會產生
違和感,覺得這樣寫怪怪的。你寫 10.0f 時就會考慮 10.5f 會發生什麼事
3. 最後註解 Unreached 其實很有必要,照我的寫法所有狀況都應該在 if-else 的
結構內 return,所以不會跑到 Unreached 那邊。但就是有些人在修改 code 時
會呆呆加在後面,以為 if 跑完就會跑他加的東西,所以要註解提醒。
實務上有很多地方需要這樣的防呆措施,不只是合作寫程式防別人耍呆,很多
時候自己也會發蠢,
* * *
舉另一個經典例子:
if (unit > 1.0f)
return unit*3.0f;
這樣寫在 C/C++ 是允許的,省略大括號。但是就有人這樣插一行...
if (unit > 1.0f)
printf("Using 3.0 ratio.\n");
return unit*3.0f;
結果變成不管 unit 值多少,有沒有 print 那行字,都變成 return unit*3.0f 了
所以我會嚴格要求如果 if 的內容分成兩行寫,一定要加大括號
if (unit > 1.0f) {
return unit*3.0f;
}
或這樣也行
if (unit > 1.0f)
{
return unit*3.0f;
}
寫成同一行的話隨便你加不加
if (unit > 1.0f) return unit*3.0f;
大家應該會覺得是插入新行卻不長眼看清楚的那個人的錯,我也覺得是他的錯,
但是這種狀況實在太多太多了,大家都是用 Ctrl-C & Ctrl-V 在寫程式的樣子,
熬夜拼命貼的時候就常常貼錯地方,只好設法定一些規則防呆。
這樣至少你 code review 時就可以檢查大括號來預防出錯,而不是每次 release 的
前一天晚上才在抓幾百個這種無腦錯誤。
--
桃樂絲: 可是, 如果你沒有頭腦, 為什麼會說話?
稻草人: ㄝ, 我也不知... 但是有些人沒有頭腦也能說超~多話呢。
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 1.164.198.178
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1461828217.A.029.html
→ MOONRAKER: else if 不錯,清楚要求只有一個case執行 04/28 15:55
→ MOONRAKER: 也有人要求很長很大的if block不要用else 04/28 15:55
→ MOONRAKER: 而是要 if (flag) { ... } if (!flag) { ... } 的 04/28 15:55
→ MOONRAKER: 不過那是另外一回事情 04/28 15:56
推 james732: 推 04/28 20:11
推 CoNsTaR: 用 monads 來寫最方便啦 XDD 04/29 12:42
→ bibo9901: monad是個糟糕的設計 04/29 13:09
推 CoNsTaR: 是啊 它隱藏了不該隱藏的細節 可是就是方便嘛 XDD 04/29 13:13
→ bibo9901: C又沒有綁手綁腳的"純"函數 跟本不必用monad啊 04/29 13:15
推 chen20: 推推 04/29 21:59
推 david830317: 我是原PO謝謝大大的建議跟詳細的講解!! 05/23 13:12