Re: [問題] return問題

看板C_and_CPP作者 (順風相送)時間8年前 (2016/04/28 15:23), 編輯推噓5(506)
留言11則, 6人參與, 最新討論串2/2 (看更多)
※ 引述《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

04/28 15:55, , 1F
else if 不錯,清楚要求只有一個case執行
04/28 15:55, 1F

04/28 15:55, , 2F
也有人要求很長很大的if block不要用else
04/28 15:55, 2F

04/28 15:55, , 3F
而是要 if (flag) { ... } if (!flag) { ... } 的
04/28 15:55, 3F

04/28 15:56, , 4F
不過那是另外一回事情
04/28 15:56, 4F

04/28 20:11, , 5F
04/28 20:11, 5F

04/29 12:42, , 6F
用 monads 來寫最方便啦 XDD
04/29 12:42, 6F

04/29 13:09, , 7F
monad是個糟糕的設計
04/29 13:09, 7F

04/29 13:13, , 8F
是啊 它隱藏了不該隱藏的細節 可是就是方便嘛 XDD
04/29 13:13, 8F

04/29 13:15, , 9F
C又沒有綁手綁腳的"純"函數 跟本不必用monad啊
04/29 13:15, 9F

04/29 21:59, , 10F
推推
04/29 21:59, 10F

05/23 13:12, , 11F
我是原PO謝謝大大的建議跟詳細的講解!!
05/23 13:12, 11F
文章代碼(AID): #1N8Rfv0f (C_and_CPP)
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 2 篇):
文章代碼(AID): #1N8Rfv0f (C_and_CPP)