錯誤與編程——拋棄 C程式設計 中的謬誤與惡習

來源:互聯網
上載者:User

《品悟C——拋棄 C程式設計 中的謬誤與惡習》——前言

  • 這是一本什麼樣的書

  這是一本關於C程式設計常見錯誤的書。書中詳盡地剖析、討論了學習或使用C語言過程中常見的一些錯誤觀念和錯誤實踐。目的是協助讀者更準確地理解並運用C語言。

  • 為什麼要寫這樣一本書

  因為錯誤與程式設計一向如影隨形,密不可分。只要編寫程式,就無法避免錯誤。這是一條鐵律。無論是初出茅廬的新手還是經驗豐富的老手,無一例外。從某種意義上來說,軟體業的主要工作有三項:製造錯誤、改正錯誤和掩飾錯誤。因此不深入瞭解和認識錯誤就不可能真正懂得編程。

  孔子說:“未知生,焉知死?”程式設計也是這個道理,不懂得錯誤就不可能真正理解程式設計語言的要點及編程的真諦。實踐表明,人們從錯誤中學習到的東西往往比從正確中學到的多得多。這就是人們常說的“吃一塹,長一智”。

  事實上每個程式員的成長曆程都是一部不斷認識錯誤並予以改正的錯誤修正史。每一個優秀的程式員無一不是從無數的錯誤中脫穎而出的,並且始終要與錯誤進行不懈地鬥爭。閃光的思想一向少不得經曆錯誤的磨礪。

  從這個角度來看,對程式設計中的錯誤進行討論比那些一本正經地正確敘述更有助於程式設計人員水平的提高,本書的目的就在於此。

  然而儘管市場上C語言的書籍多得可以車載鬥量,但遺憾的是幾乎鮮有專門論述C程式設計中錯誤的書籍,除了Koenig所著的《C陷阱與缺陷》。不過我覺得作者Koenig先生“闡之未盡,我有我的看法”。

  實際上Koenig先生並不瞭解中國國情,他不知道程式設計中的錯誤其實分為兩種,一種是錯誤,另一種是中國式錯誤。一句話,他根本無法想象我們是用品質何等奇特的教科書、用何等落後的方式學習C編程。因此他的書只提到了普通的一般性錯誤,而對形形色色的具有中國特色的錯誤卻隻字未提。這是一個巨大的、需要填補的空白(我不知道這算不算學術空白,從某種意義上來說這更像是清除技術汙染)。這項工作目前來看還沒有人做。既然古代的聖賢曾經教誨過我們應該“當仁不讓”,所以現在只好由本書來勉為其難了。

  • 錯誤是怎樣“煉”成的

  眾所周知,所謂編程在本質上無非是用特定的形式語言向電腦描述一個問題的解決方案。在此之前,對這種語言的學習也是一個必不可少的環節。在整個過程中的一系列環節的任何一個環節上都可能會出現錯誤。

  首先,語言的學習過程中會產生許多錯誤。這些錯誤不僅是因為學習者自身的原因,同時也是由於教科書方面的原因。

  許多虔誠的學習者內心的潛意識裡會以為教科書不會有什麼錯誤,他們一向跪在教科書上學習,遇到錯誤時只是不斷地檢討自己。在這個連嬰兒奶粉都可能含有三聚氰胺的社會,懷有這種念頭實在是too naive了。沒有任何理由指望你的教科書比嬰兒奶粉更純淨。

  教科書同樣可能有錯,這種“水源”的汙染才是最嚴重的汙染。在這種情況下,只尋找自身出錯的原因是不可能解決問題的。這種先入為主的錯誤非常難以糾正,而且其影響往往也最為深遠。例如,很多人在成為職業程式員之後也還不清楚

  a+=a-=a*a

這個運算式是不正確的。

  對語言不夠熟悉是初學者犯錯誤的另一個主要原因。通常表現為代碼裡不是缺點兒什麼就是多點兒什麼。這種錯誤是一種最初級的錯誤,連編譯器能夠指出,因而比較容易得到糾正,所以多半不足為慮。

  學習一種語言,本質上就是為了學習一種新的思維方式。將平時不嚴謹的自然語言思維習慣帶入程式經常會導致對程式設計語言的誤解,例如把“x不等於1或2”錯誤地表達為

  x!=1||x!=2

  甚至我們所熟悉的嚴謹的數學語言,由於語境發生了變化,也會在程式中帶來錯誤。例如,很多人都犯過把“==”(“等於”)寫成數學中的“=”(“賦值”,在數學領域表示“等於”)這種錯誤。這種錯誤一般需要通過長期的自覺訓練來糾正。

  往往被初學者所忽視的是不良編程習慣的問題,他們一心只想著寫正確的代碼,而從不考慮如何正確地寫出正確的代碼。這往往會導致許多低級錯誤一犯再犯,比如一再出現括弧不成對這樣的問題。

  缺乏良好的編程習慣是寫不好程式的,任何一個工人都懂得:良好的產品品質需要由合理的工藝來保證。不懂得正確地編寫程式就幾乎不可能寫出正確的程式。

  初學者忽視不良習慣的另一個主要原因是,這些編程陋習有時並不能在短期內顯示出其惡果,比如“int a,b,c;”這種爛得不能再爛的變數名。實際上良好編程習慣的意義不僅在於避免錯誤,還在於它意味著少犯錯誤,或者在出現錯誤時很容易檢查到並修正,這些長遠的利益在短時間內一般是體會不到的。

  良好的習慣要靠自覺培養,但是如果教科書沒告訴你這些,那是教科書的問題。因為初學者不可能在短時間內完全靠自己的悟性領會前人幾十年積累下來的編程規範方面的經驗。順便說一句,有些教科書的代碼風格本身就極濫無比,對初學者誤導很大。

  僅僅熟悉語言元素對於編程來說是遠遠不夠的,因為每一個程式的目標都是為瞭解決問題。而從問題到程式要經曆問題的提出、問題的分析到問題的解決,最後落實為代碼,在這一過程中每一個步驟都可能會出現錯誤。

  正確地提出問題是解決問題的先決條件,錯誤的問題是不可能解決的。例如,要求“輸出1~n*n的自然數構成的魔方陣”就是一個錯誤的問題,因為2階的魔方陣根本不存在。求解這樣的問題,可以說是未解先錯。

  問題提出模糊不清的要求也是一種錯誤,例如“有三個數a、b、c,要求按大小順序把它們輸出”,這裡的三個數究竟是什麼數,是模糊不清的,在不同的情況下代碼截然不同。要求應該明確。要求不清是提出者的錯誤,但擅自猜測問題的要求則是程式員的錯誤。

  編寫求解錯誤問題或不嚴謹問題的程式有害無益,而且貽害無窮,這會使程式員在不知不覺中喪失必要的職業嚴謹,對錯誤的需求漸漸層得麻木不仁。要知道,在真實的開發中,因為軟體需求錯誤而導致的軟體錯誤佔到錯誤總數的一半以上,而且那些錯誤的需求往往不那麼清楚明顯、容易察覺。不具備審視問題或要求是否合理的習慣和能力,在真正的軟體開發中就如同盲人騎瞎馬,不可能不掉到溝裡。

  初學者中很少有人意識到問題本身可能就是錯誤的。很多初學者常常不管三七二十一地解決錯誤的問題。這對他們的邏輯思維能力是一種巨大的慢性戕害。

  即使正確地提出了問題,也還可能被程式設計者所誤解。錯誤地理解問題的要求,同樣是錯誤產生的一個重要原因。

  分析問題的過程中最容易產生邏輯錯誤,或者對問題分析得不全面導致的顧此失彼。這種不全面的邏輯漏洞往往比完全的邏輯錯誤更難發現,因為這時程式的運行有可能會“顯得”是正確的。

  即使沒有前面提到的那些錯誤,距離寫出優秀的代碼還有很長的路。寫代碼和寫文章一樣,需要精心地進行布局謀篇,用術語來說就是進行設計。

  設計不僅包括演算法設計還包括對資料結構的設計。在“演算法——程式的靈魂”這種片面觀點的誤導下,很多人輕視資料結構的設計,冥思苦想所謂的演算法。實際上演算法和資料結構是密不可分的,那些艱深晦澀的糟糕演算法,大多是因為垃圾的資料結構設計。

  有些人寫程式毫無設計意識,上來就開始匆忙寫代碼,東一榔頭西一棒槌,寫到哪算哪,寫出的代碼笨拙無比、僵硬造作、邏輯混亂、囉唆重複或者效率低下。這樣的代碼即使能輸出結果,也是不合格的醜陋代碼。

  難道程式長得醜陋也是一種錯誤嗎?是的,作為一種藝術,程式有自己的美學標準。從微觀上看,這種美感表現為充分體現語言的優美和風格的簡潔;從宏觀來看則表現為一種層次清晰和條理分明。這種標準並不出於純粹的審美,也有其功用價值——不容易出錯,發生錯誤容易改正。而要達到這一目標,程式設計實踐過程離不開正確的哲學指導,這種哲學的一個核心理念就是結構化程式設計思想。

  至此,儘管還有很多種類錯誤沒有談到,但是已經不難得出結論,程式設計錯誤很多。需要始終對錯誤保持警惕。

  • 應該如何對待程式設計中的錯誤

  首先,不要懼怕錯誤。錯誤儘管繁多,但只要瞭解認識錯誤就可以改正、避免錯誤。最可怕的是對錯誤的無知與鴕鳥般的無視。認識錯誤是改正錯誤的前提。

  其次,瞭解錯誤越早越好,瞭解得越多越好。瞭解得越早進步得越快,瞭解得越多進步越大。

  第三,錯誤也是一種財富。既然從錯誤中積累經驗是提高程式設計水平的必經之路,那麼從他人的錯誤中吸取教訓則是一種提高程式設計水平的捷徑,因為所謂捷徑無非就是少走彎路或不走彎路而已。

  • 本書的主要內容及特點

  本書彙集了大量C語言的錯誤和編程陋習,逐個予以詳細討論,這些錯誤主要取自國內發行量和影響力較大的C語言教科書及其他一些非教科書C語言書籍以及網路上比較流行的觀點,主要包括□□□□□(為節約篇幅,此處刪去286個字),也有一些則是C語言本身的一些不易理解的特點以及學習者不具備良好的編程習慣所導致的錯誤。應該說本書所舉出的反面例子非常具有代表性。

  本書分為上下兩部,上部“形而下學”討論代碼中的常見錯誤和不良風格,下部“形而上學”討論的是很多人對C語言持有的錯誤觀點和認識。

  書中各個小節基本上是互相獨立的,因此讀這本書並不需要循序漸進,可以翻到哪頁讀哪頁。

  • 什麼人應該及什麼人不應該看這本書

  對於使用國內教科書學習C語言的人來說,無論是初學者還是職業程式員,這本書應該是很有價值的參考讀物。因為本書的內容恰恰是教科書不講的內容或恰恰是教科書講錯了的內容。

  如果是為了應付什麼等級考試之類的話,就不需要浪費錢財了。看了此書你可能會發現那些考試本身也有很多錯誤。

  • 閱讀指南

  (此處刪略)

  雖然為寫這本書花了近三年的時間,但最後完稿時,我發現這段時間依然顯得非常短促。因此儘管這是一本討論錯誤的書,但是毋庸諱言,它本身可能也免不了存在錯誤。

  您若在閱讀時發現任何錯誤或不妥之處,歡迎與作者聯絡並通知作者:pmerofc@126.com。這裡先謝了!

  本書的勘誤將發布在作者的部落格:http://blog.chinaunix.net/uid/22996974.html和http://www.cnblogs.com/pmer/。

  • 致謝

  本書的寫作過程中得到了很多人的協助和支援,在此作者表示深深的感謝。

  特別感謝starwing83網友的一貫支援和協助,他對程式設計語言的深刻理解和豐富的實踐經驗不但讓筆者受益匪淺,而且也使本書在許多方面得到了提高和充實。本書的第11章問題28、第18章問題10和第19章問題1為starwing83網友所撰寫。

  特別感謝OwnWaterloo網友的一貫支援和協助,他對標準的準確理解和對程式設計深刻的洞悉解開了筆者的很多疑惑,使作者在很多問題上都茅塞頓開。第5章“問題19”為OwnWaterloo網友所撰寫。

  特別感謝幻の上帝網友,在多年的共同探討中,他熱情而無私地給予作者很多支援、協助和啟迪。本書的很多觀點受惠於幻の上帝網友的啟迪,他還為本書收集了很多資料,為本書做了許多翔實的考證工作,並糾正了作者的很多錯誤。

  特別感謝諸多網友在長期的討論中所給予的道義支援、精神鼓勵和技術協助,他們是:變異老鼠、shan_ghost、蔡萬釗、狗氣球、狗蛋、三月二十七、tempname2、x5miao、madoldman、walleeee、ChiyuT、davelv、huangzhenfan、花瓣雪、一介村夫、wait_rabbit、MMMX、rover12421、良化綱領_、assiss、gccer、8pm、supermegaboy、A.com、noword2k、hahajerry007、ztz0223、Ray001、fera、unixlinuxsys、cokeboL、koolcoy、sh19871122、群雄逐鹿中原、fender0107401、jerryz920、hellioncu、blueheavenljn、x2、lylesong、supersuper8、gaara99、Kabie、pkkj、rossini23、wolfkin、milujite、weixuejun、cnhbdu、yesBSD、kouu、chinesedragon、water_wf、gz80、toniz、eminem112、sunjiakuang、airjordanforce、yumaofsj、yug1129、campuspuzzle、www1862、zxrjkl、peijue、jhzhu_snps、x75yan、zhaohongjian000、tinysniper、xxwpk007、geel、字母二十六、奶茶dsk、abc976031617、rain_fish、amarant、財版、沒本、grand508、star1983653、bill15、makeit、liexusong、pandaiam、txg531、kingwolf520、梅川內依酷、bukkake、wuxb45、hobbs136、cjaizss、greensnow、jhui66、luojiannx、耐心學習、xiaobenniao514、L_kernel、geruihai、erlangs、A13433758072、CUXXXCU、ip200、Hongqiyaodao、dglwx、jhinux、xwxfirst、timesu、srdgame、septem776、liupingforarm、kellenforever、192redwolf、cobras、small_bee、gyarenas、jack4010、startn、rainysky、jimmyixy、litanhe、rubyish、Demon—Hunter、wuliming_sc、bigxu、xfoucs、時尚農民、yangxue1206、hukb_cu、jnbxzl0200157、tianshx、sukora、ux400、craneflyfly、autoasm、時間看來、Jokday、asuka2001、namiii、jeung、btdm123、lilery、wangzhen11aaa、nketc、KanonInD、ybh37、dahan16、digdeep126、keytounix、光明-使者、gtv、SoforthHe、djsxut、oilgeo、獃獃的等候救贖、hbmhalley、china_ssl、solu、dajiangyou77、wl85125771、魔獸_LOVER、0xC1988、inzahgi、武林萌豬、lilinly225、wgm001、royalzhang、千年老狼、musezh2、gooderfeng、HAL9000、Jack_Jack、大石頭、萬倉一黍、Ivony、愚溪、nscboy、minvt、underuwings、Artech、ini_always、小彬、xujif、Leon Sharp、劉博平、linyilong、浩然正氣89、backag、happycat1988、ygcao、rhs、Zlinux、小_金_魚、泡泡騰、SongSharp、szwe、eeeyes、+v、linxr、andreas、冠吸柏汁霆瘋、九原山人、火禾、luotong、Programmer K、hachihe、rockyoung、czcz1024、Edgar Wang、magicDict、hoodlum1980、空明流轉、隨風浪跡天涯、不死鳥之魂、木耳、木野狐(Neil Chen)、散客遊、sunriseyuen、chasefornone、飛浪、glshader、Credo、wcut、houqidian、Parry、xiekun605746、哥哥.Net、Virus-BeautyCode、莊金峰、我想我是風、Mien Ng、soap、greenhand2008、Homer_Simpson、zsea、鎏、ctou45、shamo0303、gussing、eflay、王小兵、l23cy、winter-cn、Lee.Kevin、陽光明媚Ryan、地獄門神、richardzeng、pulihe、寒靄、cncolder、陳玉國、是否存在、key yao、codebumb、☆凱子、darklx、草珊瑚、鶴衝天、Jake Lin、Lithium、幹拔三分、leizisdu、zzuxiaolei、BitSky、Jeffrey Zhao、桀驁的靈魂、海南.胡勇、sm11e、我寫的不是代碼 是寂寞、lzyzizi、肖璟、嗷嗷、木+頭、zy498420、№完成、五星、Simon-Zhu、BeckFun、Tony Zhou、lxlylm、陳梓瀚(vczh)、zdd、xchat、frank_hust、漂浮的雨、六芒星、MagicHu、天方、深藍流沙、viperchaos、swfc_qinmm、瀟湘雨歇、riccc、Jeff Wong、wincss、reavics、weiwelcome0、Muse、lx458004975、鏡美如、volcanol、路過秋天、徐少俠、南京.王清培、諾貝爾、藺燕梅……這個名單可能有所遺漏,在此向被遺漏的網友表示歉意。

  特別感謝ChinaUnix論壇,在這個論壇的《以其昏昏使人昭昭》文章中我完成了這本書的主要素材的積累。這個論壇良好的技術氛圍使得本書素材的積累得以順利進行。

  特別感謝部落格園,作者在這個論壇發表的《C解毒》系列博文是本書的部分內容或草稿。在這個論壇得到了很多網友有益的反饋。

  本書在寫作過程中參閱了大量網上技術資料,從中得到了很多啟發,鄭重向這些作者表示謝意。

  一位朋友根據《以其昏昏使人昭昭》文章整理了一份文檔,給本書的寫作帶來了極大的便利和協助,在此深深表示感謝。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.