標(biāo)簽(空格分隔): 翻譯 技術(shù) C/C++ 作者:Andrey Karpov 翻譯者:顧笑群 - Rafael Gu 最后更新:2017年02月05日
我們這里要說(shuō)的和之前說(shuō)到的“不要試圖把盡量多的操作符放到一行代碼里”有一些類(lèi)似,但這次我想聚焦于另外一個(gè)方面。有時(shí)候我們程序員充滿斗志,好像在和某人比賽一般,然后就會(huì)寫(xiě)一些盡量短(譯者注:而且故意很難讀看上去很高深的代碼)。
我這里并非說(shuō)的是那些復(fù)雜的模板。因?yàn)楹茈y找到明顯的界限去區(qū)分這些模板那里不好或那里好,所以這應(yīng)該是一個(gè)另外一個(gè)話題的范疇。現(xiàn)在我們這里將要討論的只是一些相關(guān)C/C++程序員的簡(jiǎn)單情況——經(jīng)常的,這些程序員會(huì)寫(xiě)很復(fù)雜的代碼,然后想表達(dá)“看我能這么玩,牛逼吧”。
下面這段代碼來(lái)自KDE4。PVS-Studio診斷的錯(cuò)誤描述為:V593 Consider reviewing the exPRession of the ‘A = B == C’ kind. The expression is calculated as following: ‘A = (B == C)’(譯者注:大意是建議review代碼,因?yàn)榫幾g器會(huì)把其中類(lèi)似A = B == C的語(yǔ)句理解為A = (B == C))。
void LDAPProtocol::del( const KUrl &_url, bool ){ .... if ( (id = mOp.del( usrc.dn() ) == -1) ) { LDAPErr(); return; } ret = mOp.waitForResult( id, -1 ); ....}解釋 在看過(guò)上面的代碼后,我一直有類(lèi)似的疑問(wèn):把代碼寫(xiě)成那樣到底是圖樣?難道節(jié)省了一行空間嗎?或者是作者想展示自己有能力把多個(gè)動(dòng)作里和在一個(gè)表達(dá)式里?
但結(jié)果是我們得到了一個(gè)典型的錯(cuò)誤模式——即使用了類(lèi)似if (A = Foo() == Error)的表達(dá)式。
比較操作符的優(yōu)先級(jí)高于賦值操作符,這就是為什么“mOp.del(usrc.dn()) == -1”表達(dá)式會(huì)先被執(zhí)行的原因,然后只有true(1)或者false(0)被賦予了id變量。
如果mOp.del()返回了‘-1’,這個(gè)函數(shù)就會(huì)終止;否則程序就會(huì)繼續(xù)執(zhí)行,而且id變量也被賦予了一個(gè)不正確的值,這個(gè)判斷也會(huì)始終等于0。
正確的代碼 我想強(qiáng)調(diào)一下:增加額外的括號(hào)并不是這個(gè)問(wèn)題的解決方法。是的,錯(cuò)誤被消除了,但這是個(gè)錯(cuò)誤的方法。
如果你靠近看,你會(huì)發(fā)現(xiàn)代碼中已經(jīng)有了額外的括號(hào)。很難判斷為何要多加這個(gè)括號(hào),也許是作者想去除編譯器警告,也許是對(duì)操作符的優(yōu)先級(jí)不確認(rèn),或者是想修復(fù)前面提到的問(wèn)題,無(wú)論如何都失敗了,所以增加額外的括號(hào)并沒(méi)有提供幫助(譯者注:其實(shí)是把括號(hào)位置放錯(cuò)了)。
但更深層次的問(wèn)題在于,如果能讓代碼不太復(fù)雜,那就不要太復(fù)雜。所以正確的代碼如下:
id = mOp.del(usrc.dn());if ( id == -1 ) {建議 不要因?yàn)閼卸瓒幌攵鄬?xiě)一行代碼:畢竟復(fù)雜的表達(dá)式難以閱讀。先做賦值,然后再比較。這樣,你會(huì)讓后來(lái)接手這些代碼的程序員更容易一些,而且還減少了犯錯(cuò)誤的幾率。
所以,我的結(jié)論是——不要裝逼。
這次這篇文章有些瑣碎,但我希望能幫助你。寫(xiě)出干凈整齊的代碼始終是更好的方式,而不是那種“看我多牛逼”的方式。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注