奶头挺立呻吟高潮av全片,成人试看120秒体验区,性欧美极品v,A片高潮抽搐揉捏奶头视频

C語言

C語言編程建議和技巧

時間:2024-10-14 00:11:14 C語言 我要投稿
  • 相關推薦

C語言編程建議和技巧

  Rob Pike 是谷歌公司最著名的軟件工程師之一,曾是貝爾實驗室 Unix 開發團隊成員,Plan 9 操作系統開發的主要領導人,Inferno 操作系統開發的主要領導人。他是締造 Go 語言和 Limbo 語言的核心人物。下面,就和小編一起來看一看C語言編程建議和技巧,希望對大家有幫助!

  介紹

  Kernighan和Plauger編寫的《The Elements of Programming Style》,是一本很重要而且公認有很大影響力的書。但有時候我覺得對于書中的簡潔規則,可以看做是一種好的烹飪方法,而不是想簡潔的表達一種哲學思維。倘若這本書聲稱應該有意義地選擇變量名稱,那么難道他們文章中對變量的命名更好?難道MaximumValueUntilOverflow比maxval更好嗎?我不這么認為。

  下面是一篇簡短的文章,總體上鼓勵在編程時應有清晰的哲學思維,而不是給予硬性規則。我并不希望你們能認可所有的東西,因為它們只是觀點,觀點會隨著時間的變化而變化。可是,如果不是直到現在把它們寫在紙上,長久以來這些基于許多經驗的觀點一直積累在我的頭腦中。因此希望這些觀點能幫助你們,了解如何規劃一個程序的細節。(我還沒有看到過一篇講關于如何規劃整個事情的好文章,不過這部分可以是課程的一部分)要是能發現它們的特質,那很好;要是不認同的話,那也很好。但如果能啟發你們思考為什么不認同,那樣就更好了。在任何情況下,都不應該照搬我所說的方式進行編程;要用你認為最好的編程方式來嘗試完成程序。請一以貫之而且毫不留情的這么做。

  歡迎您的評論。

  排版問題

  程序是一種出版物。意味著程序員們會先閱讀(也許是幾天、幾周或幾年后的你自己閱讀),最后才輪到機器。機器的快樂就是程序能編譯,機器才不在乎程序寫的有多么漂亮,可是人們應該保持程序的美觀。有時人們會過度關心:用漂亮的打印機呆板地打印出漂亮的輸出,而這些輸出只是將所有介詞用英文文本以粗體字體凸顯出來,都是些與程序無關的細節。雖然有很多人認為程序就應該像 Algol68 所描述的一樣(有些系統甚至要求照搬該風格編寫程序),可清晰的程序不會因為這樣的呈現而變得更清晰,只會使糟糕的程序變得更可笑。

  對于清晰的程序來說,排版規范一向都是至關重要的。當然,眾所周知最有用的是縮進,但是當墨水遮蓋了意圖時,就會控制住排版。因此即便堅持使用簡單的舊打字機輸出,也該意識到愚蠢的排版。避免過度修飾,比如保持注釋的簡潔和靈活。通過程序整齊一致地說出想表達的。接著往下看。

  變量命名

  對于變量名稱,長度并不是名稱的價值所在,清晰的表達才是。不常用的全局變量可能會有一個很長的名稱,像maxphysaddr。在循環中每一行所使用的數組索引,并不需要取一個比i更詳盡的名字。取index或者elementnumber會輸入更多的字母(或調用文本編輯器),并且會遮蓋住計算的細節。當變量名稱很長時,很難明白發生了什么。在一定程度上,這是排版問題,看看下面

  for(i=0to100)

  array[i]=0;

  vs.

  for(elementnumber=0to100)

  array[elementnumber]=0;

  現實例子中的問題會變得更糟。所以僅需把索引當成符號來對待。

  指針也需要合理的符號。np僅僅只是作為指針 nodepointer 的助記符。如果一貫都遵從命名規范,那么很容易就能推斷出 np 表示“節點指針”。在下一篇文章中會提到更多。

  同時在編程可讀性的其它方面,一致性也是極其重要的。假使變量名為 maxphysaddr,則不要給同級關系的變量取名 lowestaddress。

  最后,我傾向于「最小長度」但「最大信息量」的命名,并讓上下文補齊其余部分。例如:全局變量在使用時很少有上下文幫助理解,那么它們的命名相對而言更需要令人易懂。因此我稱 maxphyaddr (不是 MaximumPhysicalAddress)作為一個全局變量名,對于在本地定義和使用的指針來說 np 并不一定是 NodePoint。這是品味的問題,但品味又與清晰度相關。

  我避免在命名時嵌入大寫字母;在我經驗豐富的雙眼中,它們的閱讀舒適性太別扭了,像糟糕的排版一樣令人心煩。

  指針的使用

  C 語言不同尋常,因為它允許指針指向任何事物。指針是鋒利的工具,像任何這樣的工具一樣,使用得當可以產生令人愉悅的生產力,但使用不當也可以造成極大的破壞(在寫這篇文章的前幾天,我把木工鑿插到拇指里了)。指針在學術界的名聲不太好,因為它太危險了,莫名其妙地就變得糟糕的不行。但我認為它是強大的符號,它可以幫助我們清楚地自我表達。

  思考:當有指針指向對象時,對于那個對象,確切地說它只是名稱,其它什么也不是。聽起來很瑣碎,但看看下面的兩個表達式:

  np

  node[i]

  第一個指向一個 node(節點),第二個計算為(可以說)同一個 node。但第二種形式是不太容易理解的表達式。這里解釋一下,因為我們必須要知道 node 是什么,i是什么,還要知道i和 node 與周圍程序之間相關(可能不是很詳細)的規則是什么。孤立的表達式并不能說明i是 node 的有效索引,更不用提是我們想要元素的索引。如果i、j和k都是 node 數組中的索引將很容易出差錯,而且連編譯器都不能幫助找出錯誤。當給子程序傳參數時,尤其容易出錯:指針只是一個單獨的參數;但在接收的子程序中必須認為數組和索引是一體的。

  計算為對象表達式本身,比該對象的地址更不易察覺,而且容易出錯。正確使用指針可以簡化代碼:

  parent->link[i].type

  vs.

  lp->type.

  如果想取下一個元素的 type 可以是

  parent->link[++i].type

  或

  (++lp)->type.

  i前移,但其余的表達式必須保持不變;用指針的話,只需要做一件事,就是指針前移。

  把排版因素也考慮進來。對于處理連續的結構體來說,使用指針比用表達式可讀性更好:只需要較少的筆墨,而且編譯器和計算機的性能消耗也很小。與此相關的問題是,指針類型會影響指針正確使用,這也就允許在編譯階段使用一些有用的錯誤檢測,來檢查數組序列不能分開。而且如果是結構體,那么它們的標簽字段就是其類型的提示。因此

  np->left

  是足以讓人明白的。如果是索引數組,數組將取一些精心挑選的名字,而且表達式也會變得更長:

  node[i].left.

  此外,由于例子變得越來越大,額外的字符更加讓人惱火。

  一般來說,如果發現代碼中包含許多相似并復雜的表達式,而且表達式計算為數據結構中的元素,那么明智地使用指針可以消除這些問題。考慮一下

  if(goleft)

  p->left=p->right->left;

  else

  p->right=p->left->right;

  看起來像利用復合表達式表示p。有時這值得用一個臨時變量(這里的 p)或者把運算提取成一個宏。

  過程名稱

  過程名稱應該表明它們是做什么的,函數名稱應該表明它們返回什么。函數通常在像if這樣的表達式使用,因此可讀性要好。

  if(checksize(x))

  是沒有太大幫助的,因為不能推斷出 checksize 錯誤時返回 true,還是非錯誤時返回。相反

  if(validsize(x))

  使這點能清晰表達,并且在常規使用中將來也不大可能出錯。

  注釋

  這一個微妙的問題,需要自己體會和判斷。由于一些原因,我傾向于寧可清除注釋。第一,假如代碼清晰,并且使用了規范的類型名稱和變量名稱,應該從代碼本身就可以理解。第二,編譯器不能檢查注釋,因此不能保證準確,特別是代碼修改過以后。誤導性的注釋會非常令人困惑。第三,排版問題:注釋會使代碼變得雜亂。

  但有時我會寫注釋,像下文一樣僅僅只是把它們用于介紹。例如:解釋全局變量的使用和類型(我總是在龐大的程序中寫注釋);作為一個不尋常或者關鍵過程的介紹;或標記出大規模計算的一節。

  糟糕注釋風格,有一個典型的例子:

  i=i+1;/* Add one to i */

  還有更爛的做法:

  /**********************************

  **

  *Add one to i*

  **

  **********************************/

  i=i+1;

  先不要嘲笑,等到在現實中看到再去吧。

  或許除了諸如重要數據結構的聲明(對數據的注釋通常比對算法的更有幫助),這樣至關重要部分之外,需要避免對注釋的“可愛”排版和大段的注釋;基本上最好就不要寫注釋。如果代碼需要靠注釋來說明,那最好的方法是重寫代碼,以便能更容易地理解。這就把我們帶到了復雜度。

  復雜度

  許多程序過于復雜,比需要有效解決的問題更加復雜。這是為什么呢?大部分是由于設計不好,但我會跳過這個問題,因為這個問題太大了。然而程序往往在微觀層面就很復雜,有關這些可以在這里解決。

  規則 1:不要斷定程序會在什么地方耗費運行時間。

  瓶頸總是出現在令人意想不到的地方,直到證實瓶頸在哪,不要試圖再次猜測并加快運行速度。

  規則 2:估量(measure)

  在沒有對代碼做出估量之前不要優化速度,除非發現最耗時的那部分代碼,要不也不要去做。

  規則 3:當 n 很小時(通常也很小),花哨的算法運行很慢。

  花哨算法有很大的常數級別復雜度。在你確定 n 總是很大之前, 不要使用花哨算法。(即使假如 n 變大,也優先使用規則 2).例如,對于常見問題,二叉樹總比伸展樹高效。

  規則 4:花哨的算法比簡單的算法更容易有 bug,而且實現起來也更困難

  盡量使用簡單的算法與簡單的數據結構。

  以下幾乎是所有實際程序中用到的數據結構:

  數組

  鏈表

  哈希表

  二叉樹

  當然也必須要有把這些數據結構靈活結合的準備,比如用哈希表實現的符號表,其中哈希表是由字符型數組組成的鏈表。

  規則 5:以數據為核心

  如果選擇了適當的數據結構并把一切都組織得很有條理性,算法總是不言而喻的。編程的核心是數據結構,而不是算法。(參考 Brooks p. 102)

  規則 6:就是沒有規則 6

  數據編程

  不像許多 if 語句,算法或算法的細節通常以緊湊、高效和明確的數據進行編碼。眼前的工作可以編碼,歸根到底是由于其復雜性都是由不相干的細節組合而成。分析表是典型例子,它通過一種解析固定、簡單代碼段的形式,對編程語言的語法進行編碼。有限狀態機特別適合這種處理形式,但是幾乎任何涉及到對構建數據驅動算法有益的程序,都是將某些抽象數據類型的輸入“解析”成序列,序列會由一些獨立“動作”構成。

  也許這種設計最有趣的地方是表結構有時可以由另一個程序生成(經典案例是解析生成器)。有個更接地氣的例子,假如操作系統是由一組表驅動,這組表包含連接 I/O 請求到相應設備驅動的操作,那么可以通過程序“配置“系統,該程序可以讀取到某些特殊設備與可疑機器連接的描述,并打印相應的表。

  數據驅動程序在初學者中不常見的原因之一是由于 Pascal 的專制。 Pascal 像它的創始人一樣,堅信代碼要和數據分開。因而(至少在原始形式上)無法創建初始化的數據。與圖靈和馮諾依曼的理論背道而馳,這些理論可都是定義存儲計算機的基本原理。代碼和數據是一樣的,或至少可以算是。還能怎樣解釋編譯器的工作原理呢?(函數式語言對 I/O 也有類似的問題)

  函數指針

  Pascal 專制的另一個結果是初學者不使用函數指針。(在 Pascal 中沒有把函數作為變量) 用函數指針來處理編碼復雜度會有一些令人感興趣的地方。

  指針指向的程序有一定的復雜度。這些程序必須遵守一些標準協議,像要求一組都是相同調用的程序就是其中之一。除此之外,所要實現的只是完成業務,復雜度是分散的。

  有個協議的主張是既然所有使用的功能相似,那么它們的行為也必須相似。這對簡單的文檔、測試、程序擴展和甚至使程序通過網絡分布都有幫助——遠程過程調用可以通過該協議進行編碼。

  我認為面相對象編程的核心是清晰使用函數指針。規定好要對數據執行的一系列操作,以及對這些操作響應的整套數據類型。將程序合攏到一起最簡單的方法是為每種類型使用一組函數指針。簡而言之,就是定義類和方法。當然,面向對象語言提供了更多更漂亮的語法、派生類型等等,但在概念上幾乎沒有提出額外的東西。

  數據驅動程序與函數指針的結合,變成了一種表現令人驚訝的工作方法。根據我的經驗,這種方法經常會產生驚喜的結果。即使沒有面向對象語言,無需額外的工作也可以獲得 90% 的好處,并且能更好地管理結果。我無法再推薦出更高標準的實現方式。我所有的程序都是由這種方式組織管理,而且經過多次開發后都相安無事——遠遠優于缺少約束的方法。也許正如所說:從長遠來看,約束會帶來豐厚的回報。

  包含文件

  簡單規則:包含(include)文件時應該永遠不要嵌套包含。

  如果聲明(在注釋或隱式聲明里)需要的文件沒有優先包含進來,那么使用者(程序員)要決定包含哪些文件,但要以簡單的方式處理,并采用避免多重包含的結構。多重包含是系統編程的禍根。將文件包含五次或更多次來編譯一個單獨的 C 源文件的事情屢見不鮮。Unix 系統中 /usr/include/sys 就用了這么可怕的方式。

  說到 #ifdef,有一個小插曲,雖然它能防止讀取兩次文件,但實際上經常用錯。#ifdef 是定義在文件本身中,而不是文件包含它。結果是常常導致讓成千上萬不必要的代碼通過詞匯分析器,這是(優秀編譯器中)耗費最大的階段。

  只需遵從以上簡單規則。

【 C語言編程建議和技巧】相關文章:

C語言高效編程的小技巧09-13

C語言高效編程的4個小技巧10-27

C語言編程基礎08-17

C編程語言概述10-20

怎樣學習c++c語言編程10-26

C語言入門什么是編程語言10-12

C語言socket編程的方法10-07

如何學習C語言編程10-28

c語言編程軟件有哪些09-09

C語言高效編程的幾個絕招09-11

主站蜘蛛池模板: 通州市| 宁明县| 博白县| 修文县| 中超| 龙胜| 磴口县| 颍上县| 隆德县| 巴塘县| 乌兰察布市| 贡山| 黄龙县| 扎兰屯市| 谢通门县| 文昌市| 隆回县| 东乌| 宝应县| 临湘市| 呈贡县| 海南省| 临江市| 黄梅县| 宁蒗| 邳州市| 和龙市| 于都县| 湘潭县| 怀集县| 荣成市| 临清市| 乾安县| 名山县| 海林市| 土默特右旗| 太湖县| 隆德县| 固原市| 苗栗市| 雷州市|