




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、C語言編程規(guī)范對于程序員來說,能工作的代碼并不等于“好”的代碼?!昂谩贝a的指標很多,包括易讀、易維護、易移植和可靠等。其中,可靠性對嵌入式系統(tǒng)非常重要,尤其是在那些對安全性要求很高的系統(tǒng)中,如飛行器、汽車和工業(yè)控制中。這些系統(tǒng)的特點是:只要工作稍有偏差,就有可能造成重大損失或者人員傷亡。一個不容易出錯的系統(tǒng),除了要有很好的硬件設計(如電磁兼容性),還要有很健壯或者說“安全”的程序。然而,很少有程序員知道什么樣的程序是安全的程序。很多程序只是表面上可以干活,還存在著大量的隱患。當然,這其中也有C語言自身的原因。因為C語言是一門難以掌握的語言,其靈活的編程方式和語法規(guī)則對于一個新手來說很可能會成
2、為機關重重的陷阱。同時,C語言的定義還并不完全,即使是國際通用的C語言標準,也還存在著很多未完全定義的地方。要求所有的嵌入式程序員都成為C語言專家,避開所有可能帶來危險的編程方式,是不現(xiàn)實的。最好的方法是有一個針對安全性的C語言編程規(guī)范,告訴程序員該如何做。本規(guī)范在制定過程中,主要參考了業(yè)界比較推崇的華為軟件編程規(guī)范和范例和MISRA 2004規(guī)則,適合C語言初學者使用,目的在于在教學中培養(yǎng)學生良好的編程規(guī)范和意識、素質,促進所設計程序安全、健壯、可靠、可讀與可維護(程序簡單、清晰)??紤]到面向的是初學者,為便于教學和課程考核操作,本規(guī)范中的要求比較基本。事實上,很多公司都有自己規(guī)定的代碼風格
3、,包括命名規(guī)則、縮進規(guī)則等,學生參加工作后,應再進一步學習和應用公司的規(guī)范。建議學生在學習本規(guī)范的同時,花點時間閱讀本規(guī)范的參考文獻原文,特別是熟讀本規(guī)范的參考文獻之一的“安全第一”的C語言編程規(guī)范,深刻理解編程規(guī)范與程序安全、健壯、可靠、可讀、可維護間的關系和作用,在學習和工作中養(yǎng)成良好的編程風格。1 排版1.1 嚴格采用階梯層次組織程序代碼函數(shù)或過程的開始、結構的定義及循環(huán)、判斷等語句中的代碼都要采用縮進風格,case 語句下的情況處理語句也要遵從語句縮進要求。程序塊的分界符(如C/C+ 語言的大括號 和)應各獨占一行并且位于同一列,同時與引用它們的語句左對齊。在函數(shù)體的開始、類的定義、結
4、構的定義、枚舉的定義以及if 、for 、do 、while 、switch 、case 語句中的程序都要采用如上的縮進方式。各層次縮進的風格采用TAB縮進(TAB寬度原則上使用系統(tǒng)默認值,TC使用8空格寬度,VC使用4空格寬度)。示例:if (x is true)we do yelseif (a > b).else.和:if (x = y).else if (x > y).else.注意,右括號所在的行不應當有其它東西,除非跟隨著一個條件判斷。也就是do-while語句中的“while”,象這樣:dobody of do-loop while (condition);說明:代碼離
5、不開縮進,縮進背后的思想是:清楚地定義一個控制塊從哪里開始,到哪里結束。尤其是在你連續(xù)不斷的盯了20個小時的屏幕后,如果你有大尺寸的縮進。你將更容易發(fā)現(xiàn)縮進的好處。關于縮進主要有兩個爭論,一個是該用空格(Space)還是用制表符(Tab),另外一個是該用4格縮進還是8格縮進甚至都不是。建議總是使用Tab縮進,因為幾乎所有的代碼(不僅僅是C代碼)都在使用Tab縮進?,F(xiàn)在,有些人說8個字符大小的縮進導致代碼太偏右了,并且在一個80字符寬的終端屏幕上看著很不舒服。對這個問題的回答是:如果你有超過3個級別的縮進,你就有點犯糊涂了,應當修改你的程序。簡而言之,8個字符的縮進使程序更易讀,而且當你把功能隱
6、藏的太深時,多層次的縮進還會對此很直觀的給出警告。要留心這種警告信息。例外:對于由開發(fā)工具自動生成的代碼可以有不一致。1.2 及時折行較長的語句(>80 字符)要分成多行書寫,長表達式要在低優(yōu)先級操作符處劃分新行,操作符放在新行之首,劃分出的新行要進行適當?shù)目s進(至少1個TAB位置),使排版整齊,語句可讀。示例:report_or_not_flag = (taskno < MAX_ACT_TASK_NUMBER)&& (n7stat_stat_item_valid (stat_item)&& (act_task_tabletaskno.result_
7、data != 0);循環(huán)、判斷等語句中若有較長的表達式或語句,則要進行適應的劃分,長表達式要在低優(yōu)先級操作符處劃分新行,操作符放在新行之首。示例:if (taskno < max_act_task_number)&& (n7stat_stat_item_valid (stat_item). / program codefor (i = 0, j = 0; (i < BufferKeywordword_index.word_length)&& (j < NewKeyword.word_length); i+, j+). / program co
8、defor (i = 0, j = 0;(i < first_word_length) && (j < second_word_length);i+, j+). / program code若函數(shù)或過程中的參數(shù)較長,則要進行適當?shù)膭澐?。示例:n7stat_str_compare(BYTE *) & stat_object, (BYTE *) & (act_task_tabletaskno.stat_object),sizeof (_STAT_OBJECT);n7stat_flash_act_duration( stat_item, frame_id
9、*STAT_TASK_CHECK_NUMBER+ index, stat_object );1.3 一行只寫一條語句不允許把多個短語句寫在一行中,即一行只寫一條語句。示例,如下例子不符合規(guī)范:rect.length = 0; rect.width = 0;應如下書寫rect.length = 0;rect.width = 0;1.4 if、for、do、while等語句格式規(guī)定if 、for 、do 、while 、case 、switch 、default 等語句自占一行,且if 、for 、do 、while 等語句的執(zhí)行語句部分無論多少都要加花括號。1.5 空行(1)變量說明之后必須加空
10、行。(2)相對獨立的程序塊之間應加空行。1.6 空格在兩個以上的關鍵字、變量、常量進行對等操作時,它們之間的操作符之前、之后或者前后要加空格;進行非對等操作時,如果是關系密切的立即操作符(如> ),后不應加空格。采用這種松散方式編寫代碼的目的是使代碼更加清晰。由于留空格所產生的清晰性是相對的,所以,在已經非常清晰的語句中沒有必要再留空格,如果語句已足夠清晰則括號內側(即左括號后面和右括號前面)不需要加空格,多重括號間不必加空格,因為在C/C+語言中括號已經是最清晰的標志了。在長語句中,如果需要加的空格非常多,那么應該保持整體清晰,而在局部不加空格。給操作符留空格時不要連續(xù)留兩個以上空格。
11、(1)逗號、分號只在后面加空格。int a, b, c;(2)比較操作符, 賦值操作符"="、 "+=",算術操作符"+"、"%",邏輯操作符"&&"、"&",位域操作符"<<"、""等雙目操作符的前后加空格。if (current_time >= MAX_TIME_VALUE)a = b + c;a *= 2;a = b 2;(3)"!"、""、&quo
12、t;+"、"-"、"&"(地址運算符)等單目操作符前后不加空格。*p = 'a' / 內容操作"*"與內容之間flag = !isEmpty; / 非操作"!"與內容之間p = &mem; / 地址操作"&" 與內容之間i+; / "+","-"與內容之間(4)"->"、"."前后不加空格。p->id = pid; / "->"指
13、針前后不加空格(5) if、for、while、switch等與后面的括號間應加空格,使if等關鍵字更為突出、明顯。if (a >= b && c > d)1.7 對變量的定義,盡量位于函數(shù)的開始位置(1)應避免分散定義變量。(2)同一行內不要定義過多變量。 (3)同一類的變量在同一行內定義,或者在相鄰行定義。 (4)數(shù)組、指針等復雜類型的定義放在定義區(qū)的最后。 (5)變量定義區(qū)不做較復雜的變量賦值。1.8 程序各部分的放置順序在較小的項目中,按如下順序組織安排程序各部分:(1)#include <C的標準頭文件>。(2)#include 用戶自定義的文
14、件。(3)#define 宏定義。(4)全局變量定義。(5)函數(shù)原型聲明。(6)main函數(shù)定義。(7)用戶自定義函數(shù)。以上各部分之間、用戶自定義的函數(shù)之間應加空行。注意,函數(shù)原型聲明統(tǒng)一集中放在main函數(shù)之前,不放在某個函數(shù)內部。2 注釋2.1 注釋的原則和目的注釋的原則是有助于對程序的閱讀理解,在該加的地方都加了,注釋不宜太多也不能太少,注釋語言必須準確、易懂、簡潔。通過對函數(shù)或過程、變量、結構等正確的命名以及合理地組織代碼的結構,使代碼成為自注釋的清晰準確的函數(shù)、變量等的命名,可增加代碼可讀性,并減少不必要的注釋過量的注釋則是有害的。注釋的目的是解釋代碼的目的、功能和采用的方法,提供代
15、碼以外的信息,幫助讀者理解代碼,防止沒必要的重復注釋信息。 示例:如下注釋意義不大。/* if receive_flag is TRUE */if (receive_flag)而如下的注釋則給出了額外有用的信息。/* if mtp receive a message from links */if (receive_flag)2.2 函數(shù)頭部應進行注釋函數(shù)頭部應進行注釋,列出:函數(shù)的目的/ 功能、輸入?yún)?shù)、輸出參數(shù)、返回值、調用關系(函數(shù)、表)等。示例1:下面這段函數(shù)的注釋比較標準,當然,并不局限于此格式,但上述信息建議要包含在內。/* Function: / 函數(shù)名稱 Description
16、: / 函數(shù)功能、性能等的描述 Calls: / 被本函數(shù)調用的函數(shù)清單 Called By: / 調用本函數(shù)的函數(shù)清單 Input: / 輸入?yún)?shù)說明,包括每個參數(shù)的作 / 用、取值說明及參數(shù)間關系。 Output: / 對輸出參數(shù)的說明。 Return: / 函數(shù)返回值的說明 Others: / 其它說明*/對于某些函數(shù),其部分參數(shù)為傳入值,而部分參數(shù)為傳出值,所以對參數(shù)要詳細說明該參數(shù)是入口參數(shù),還是出口參數(shù),對于某些意義不明確的參數(shù)還要做詳細說明(例如:以角度作為參數(shù)時,要說明該角度參數(shù)是以弧度(PI),還是以度為單位),對既是入口又是出口的變量應該在入口和出口處同時標明。等等。在注釋
17、中詳細注明函數(shù)的適當調用方法,對于返回值的處理方法等。在注釋中要強調調用時的危險方面,可能出錯的地方。2.3 進行注釋時的注意事項(1)建議邊寫代碼邊注釋,修改代碼同時修改相應的注釋,以保證注釋與代碼的一致性。不再有用的注釋要刪除。(2)注釋的內容要清楚、明了,含義準確,防止注釋二義性。說明:錯誤的注釋不但無益反而有害。(3)避免在注釋中使用縮寫,特別是非常用縮寫。在使用縮寫時或之前,應對縮寫進行必要的說明。(4)注釋應與其描述的代碼相近,對代碼的注釋應放在其上方或右方(對單條語句的注釋)相鄰位置,不可放在下面。除非必要,不應在代碼或表達中間插入注釋,否則容易使代碼可理解性變差。示例:如下例子
18、不符合規(guī)范。例1:/* get replicate sub system index and net indicator */repssn_ind = ssn_dataindex.repssn_index;repssn_ni = ssn_dataindex.ni;例2:repssn_ind = ssn_dataindex.repssn_index;repssn_ni = ssn_dataindex.ni;/* get replicate sub system index and net indicator */應如下書寫/* get replicate sub system index and
19、 net indicator */repssn_ind = ssn_dataindex.repssn_index;repssn_ni = ssn_dataindex.ni;(5)對于所有有物理含義的變量、常量,如果其命名不是充分自注釋的,在聲明時都必須加以注釋,說明其物理含義。變量、常量、宏的注釋應放在其上方相鄰位置或右方。示例:/* active statistic task number */#define MAX_ACT_TASK_NUMBER 1000#define MAX_ACT_TASK_NUMBER 1000 /* active statistic task number */(
20、6)數(shù)據(jù)結構聲明( 包括數(shù)組、結構、類、枚舉等) ,如果其命名不是充分自注釋的,必須加以注釋。對數(shù)據(jù)結構的注釋應放在其上方相鄰位置,不可放在下面;對結構中的每個域的注釋放在此域的右方。示例:可按如下形式說明枚舉/數(shù)據(jù)/聯(lián)合結構。/* sccp interface with sccp user primitive message name */enum SCCP_USER_PRIMITIVEN_UNITDATA_IND, /* sccp notify sccp user unit data come */N_NOTICE_IND, /* sccp notify user the No.7 net
21、work can not */* transmission this message */N_UNITDATA_REQ, /* sccp user's unit data transmission request*/;(7)全局變量要有較詳細的注釋,包括對其功能、取值范圍、哪些函數(shù)或過程存取它以及存取時注意事項等的說明。示例:/* The ErrorCode when SCCP translate */* Global Title failure, as follows */ / 變量作用、含義/* 0 SUCCESS 1 GT Table error */* 2 GT error O
22、thers no use */ / 變量取值范圍/* only function SCCPTranslate() in */* this modual can modify it, and other */* module can visit it through call */* the function GetGTTransErrorCode() */ / 使用方法BYTE g_GTTranErrorCode;(8)注釋與所描述內容進行同樣的縮排,讓程序排版整齊,并方便注釋的閱讀與理解。示例:如下例子,排版不整齊,閱讀稍感不方便。void example_fun( void )/* cod
23、e one comments */CodeBlock One/* code two comments */ CodeBlock Two應改為如下布局。void example_fun( void )/* code one comments */CodeBlock One/* code two comments */CodeBlock Two(9)將注釋與其上面的代碼用空行隔開。示例:如下例子,顯得代碼過于緊湊。/* code one comments */program code one/* code two comments */program code two應如下書寫/* code on
24、e comments */program code one/* code two comments */program code two(10)對變量的定義和分支語句(條件分支、循環(huán)語句等)必須編寫注釋。這些語句往往是程序實現(xiàn)某一特定功能的關鍵,對于維護人員來說,良好的注釋幫助更好的理解程序,有時甚至優(yōu)于看設計文檔。(11)對于switch 語句下的case 語句,如果因為特殊情況需要處理完一個case 后進入下一個case 處理(即上一個case后無break),必須在該case 語句處理完、下一個case 語句前加上明確的注釋,以清楚表達程序編寫者的意圖,有效防止無故遺漏break語句(可
25、避免后期維護人員對此感到迷惑:原程序員是遺漏了break語句還是本來就不應該有)。示例:case CMD_DOWN:ProcessDown();break;case CMD_FWD:ProcessFwd();if (.).break; elseProcessCFW_B(); / now jump into case CMD_Acase CMD_A:ProcessA();break;.(12)在程序塊的結束行右方加注釋標記,以表明某程序塊的結束。當代碼段較長,特別是多重嵌套時,這樣做可以使代碼更清晰,更便于閱讀。示例:參見如下例子。if (.)program codewhile (index &
26、lt; MAX_INDEX)program code /* end of while (index < MAX_INDEX) */ / 指明該條while語句結束 /* end of if (.)*/ / 指明是哪條if語句結束(13)在順序執(zhí)行的程序中,每隔35行語句,應當加一個注釋,注明這一段語句所組成的小模塊的作用。對于自己的一些比較獨特的思想要求在注釋中標明。(14)注釋格式盡量統(tǒng)一,建議使用“/* */”。(15)注釋應考慮程序易讀及外觀排版的因素,使用的語言若是中、英兼有的,建議多使用中文,除非能用非常流利準確的英文表達注釋語言不統(tǒng)一,影響程序易讀性和外觀排版,出于對維護人員
27、的考慮,建議使用中文。3 命名規(guī)則C是一門樸素的語言,你使用的命名也應該這樣。與Modula-2和Pascal程序員不同,C程序員不使用諸如“ThisVariableIsATemporaryCounter”這樣“聰明”的名字。C程序員應該叫它“tmp”,這寫起來更簡單,也不會更難懂。然而,當面對復雜情況時就有些棘手,給全局變量取一個描述性的名字是必要的。把一個全局函數(shù)叫做“foo”是一種目光短淺的行為。全局函數(shù)也一樣,如果你有一個統(tǒng)計當前用戶個數(shù)的函數(shù),應當把它命名為“count_active_user()”或者簡單點些的類似名稱,不應該命名為“cntusr()”。3.1 三種流行的命名法則目
28、前,業(yè)界共有四種命名法則:駝峰命名法、匈牙利命名法、帕斯卡命名法和下劃線命名法,其中前三種是較為流行的命名法。(1)駝峰命令法。正如它的名稱所表示的那樣,是指混合使用大小寫字母來構成變量和函數(shù)的名字。例如,下面是分別用駱駝式命名法和下劃線法命名的同一個函數(shù):printEmployeePaychecks();print_employee_paychecks();第一個函數(shù)名使用了駝峰命名法,函數(shù)名中的每一個邏輯斷點都有一個大寫字母來標記。第二個函數(shù)名使用了下劃線法,函數(shù)名中的每一個邏輯斷點都有一個下劃線來標記。駝峰命名法近年來越來越流行了,在許多新的函數(shù)庫和Microsoft Windows這樣
29、的環(huán)境中,它使用得當相多。另一方面,下劃線法是C出現(xiàn)后開始流行起來的,在許多舊的程序和UNIX這樣的環(huán)境中,它的使用非常普遍。(2)匈牙利命名法。廣泛應用于象Microsoft Windows這樣的環(huán)境中。Windows 編程中用到的變量(還包括宏)的命名規(guī)則為匈牙利命名法,這種命名技術是由一位能干的 Microsoft 程序員查爾斯-西蒙尼(Charles Simonyi) 提出的。匈牙利命名法通過在變量名前面加上相應的小寫字母的符號標識作為前綴,標識出變量的作用域、類型等。這些符號可以多個同時使用,順序是先m_(成員變量)、再指針、再簡單數(shù)據(jù)類型、再其它。這樣做的好處在于能增加程序的可讀性
30、,便于對程序的理解和維護。例如:m_lpszStr, 表示指向一個以0字符結尾的字符串的長指針成員變量。匈牙利命名法關鍵是:標識符的名字以一個或者多個小寫字母開頭作為前綴;前綴之后的是首字母大寫的一個單詞或多個單詞組合,該單詞要指明變量的用途。(3)帕斯卡(pascal)命名法。與駝峰命名法類似,二者的區(qū)別在于:駝峰命名法是首字母小寫,而帕斯卡命名法是首字母大寫,如:DisplayInfo();string UserName;二者都是采用了帕斯卡命名法。 (4)三種命名規(guī)則的小結:MyData就是一個帕斯卡命名的示例;myData是一個駝峰命名法,它第一個單詞的第一個字母小寫,后面的單詞首字母
31、大寫,看起來像一個駱駝;iMyData是一個匈牙利命名法,它的小寫的i說明了它的型態(tài),后面的和帕斯卡命名相同,指示了該變量的用途。3.2 命名的基本原則(1)標識符的命名要清晰、明了,有明確含義,同時使用完整的單詞或大家基本可以理解的縮寫,避免使人產生誤解盡量采用采用英文單詞或全部中文全拼表示,若出現(xiàn)英文單詞和中文混合定義時,使用連字符“_”將英文與中文割開。較短的單詞可通過去掉“元音”形成縮寫;較長的單詞可取單詞的頭幾個字母形成縮寫;一些單詞有大家公認的縮寫。例如:temp->tmp、flag->flg、statistic->stat、increment->inc、m
32、essage->msg等縮寫能夠被大家基本認可。(2)命名中若使用特殊約定或縮寫,則要有注釋說明。應該在源文件的開始之處,對文件中所使用的縮寫或約定,特別是特殊的縮寫,進行必要的注釋說明。(3)自己特有的命名風格,要自始至終保持一致,不可來回變化。個人的命名風格,在符合所在項目組或產品組的命名規(guī)則的前提下,才可使用。(即命名規(guī)則中沒有規(guī)定到的地方才可有個人命名風格)。(4)對于變量命名,禁止取單個字符(如i 、j 、k. ),建議除了要有具體含義外,還能表明其變量類型、數(shù)據(jù)類型等,但i 、j 、k 作局部循環(huán)變量是允許的。變量,尤其是局部變量,如果用單個字符表示,很容易敲錯(如i寫成j)
33、,而編譯時又檢查不出來,有可能為了這個小小的錯誤而花費大量的查錯時間。(5)除非必要,不要用數(shù)字或較奇怪的字符來定義標識符。(6)命名規(guī)范必須與所使用的系統(tǒng)風格保持一致,并在同一項目中統(tǒng)一。(7)在同一軟件產品內,應規(guī)劃好接口部分標識符(變量、結構、函數(shù)及常量)的命名,防止編譯、鏈接時產生沖突。對接口部分的標識符應該有更嚴格限制,防止沖突。如可規(guī)定接口部分的變量與常量之前加上“模塊”標識等。(8)用正確的反義詞組命名具有互斥意義的變量或相反動作的函數(shù)等。下面是一些在軟件中常用的反義詞組。add / remove begin / end create / destroyinsert / dele
34、te first / last g et / releaseincrement / decrement put / getadd / delete lock / unlock open / closemin / max old / new start / stopnext / previous source / target show / hidesend / receive source / destinationcut / paste up / down示例:int min_sum;int max_sum;int add_user( BYTE *user_name );int delete
35、_user( BYTE *user_name );(9)除了編譯開關/ 頭文件等特殊應用,應避免使用_EXAMPLE_TEST_ 之類以下劃線開始和結尾的定義。3.3 變量名的命名規(guī)則(1)變量的命名規(guī)則要求用“匈牙利法則”。即開頭字母用變量的類型,其余部分用變量的英文意思、英文的縮寫、中文全拼或中文全拼的縮寫,要求單詞的第一個字母應大寫。即: 變量名=變量類型+變量的英文意思(或英文縮寫、中文全拼、中文全拼縮寫)對非通用的變量,在定義時加入注釋說明,變量定義盡量可能放在函數(shù)的開始處。見下表:bool 用b開頭 bFlgint 用i開頭 iCountshort int 用n開頭 nStepCo
36、untlong int 用l開頭 lSumchar 用c開頭 cCountunsigned char 用by開頭float 用f開頭 fAvgdouble 用d開頭 dDetaunsigned int(WORD) 用w開頭 wCountunsigned long int(DWORD) 用dw開頭 dwBroad字符串 用s開頭 sFileName用0結尾的字符串 用sz開頭 szFileName(2)指針變量命名的基本原則為:對一重指針變量的基本原則為:“p”+變量類型前綴+命名,如一個float*型應該表示為pfStat。對二重指針變量的基本規(guī)則為:“pp”+變量類型前綴+命名。對三重指針變
37、量的基本規(guī)則為:“ppp”+變量類型前綴+命名。(3)全局變量用g_開頭,如一個全局的長型變量定義為g_lFailCount,即:變量名=g_+變量類型+變量的英文意思(或縮寫)。此規(guī)則還可避免局部變量和全局變量同名而引起的問題。(4)靜態(tài)變量用s_開頭,如一個靜態(tài)的指針變量定義為s_plPerv_Inst,即: 變量名=s_+變量類型+變量的英文意思(或縮寫)(5)對枚舉類型(enum)中的變量,要求用枚舉變量或其縮寫做前綴。并且要求用大寫。如:enum cmEMDAYSEMDAYS_MONDAY;EMDAYS_TUESDAY;(6)對struct、union變量的命名要求定義的類型用大寫。
38、并要加上前綴,其內部變量的命名規(guī)則與變量命名規(guī)則一致。結構一般用S開頭,如:struct ScmNPointint nX;/點的X位置int nY; /點的Y位置;聯(lián)合體一般用U開頭,如:union UcmLPointLONG lX;LONG lY;(7)對常量(包括錯誤的編碼)命名,要求常量名用大寫,常量名用英文表達其意思。當需要由多個單詞表示時,單詞與單詞之間必須采用連字符“_”連接。如:#define CM_FILE_NOT_FOUND CMMAKEHR(0X20B) 其中CM表示類別。(8)對const 的變量要求在變量的命名規(guī)則前加入c_,即:c_+變量命名規(guī)則;示例:const c
39、har* c_szFileName;3.4 函數(shù)的命名規(guī)范(1)函數(shù)的命名應該盡量用英文(或英文縮寫、中文全拼、中文全拼縮寫)表達出函數(shù)完成的功能函數(shù)名應準確描述函數(shù)的功能。遵循動賓結構的命名法則,函數(shù)名中動詞在前,并在命名前加入函數(shù)的前綴,函數(shù)名的長度不得少于8個字母。函數(shù)名首字大寫,若包含有兩個單詞的每個單詞首字母大寫。如果是OOP 方法,可以只有動詞(名詞是對象本身)。示例:LONG GetDeviceCount();void print_record( unsigned int rec_ind ) ;int input_record( void ) ;unsigned char get
40、_current_color( void ) ;(2)避免使用無意義或含義不清的動詞為函數(shù)命名。如使用process、handle等為函數(shù)命名,因為這些動詞并沒有說明要具體做什么。(3)必須使用函數(shù)原型聲明。函數(shù)原型聲明包括:引用外來函數(shù)及內部函數(shù),外部引用必須在右側注明函數(shù)來源: 模塊名及文件名;內部函數(shù),只要注釋其定義文件名和調用者在同一文件中(簡單程序)時不需要注釋。應確保每個函數(shù)聲明中的參數(shù)的名稱、類型和定義中的名稱、類型一致。3.5 函數(shù)參數(shù)命名規(guī)范(1)參數(shù)名稱的命名參照變量命名規(guī)范。(2)為了提高程序的運行效率,減少參數(shù)占用的堆棧,傳遞大結構的參數(shù),一律采用指針或引用方式傳遞。(
41、3)為了便于其他程序員識別某個指針參數(shù)是入口參數(shù)還是出口參數(shù),同時便于編譯器檢查錯誤,應該在入口參數(shù)前加入const標志。如:cmCopyString(const CHAR * c_szSource, CHAR * szDest)3.6 文件名(包括動態(tài)庫、組件、控件、工程文件等)的命名規(guī)范文件名的命名要求表達出文件的內容,要求文件名的長度不得少于5個字母,嚴禁使用象file1,myfile之類的文件名。4 可讀性4.1 避免使用默認的運算優(yōu)先級注意運算符的優(yōu)先級,并用括號明確表達式的操作順序,避免使用默認優(yōu)先級,可防止閱讀程序時產生誤解,防止因默認的優(yōu)先級與設計思想不符而導致程序出錯。示例:
42、下列語句中的表達式word = (high << 8) | low (1)if (a | b) && (a & c) (2)if (a | b) < (c & d) (3)如果書寫為:high << 8 | lowa | b && a & ca | b < c & d由于high << 8 | low = ( high << 8) | low,a | b && a & c = (a | b) && (a & c),(1)(2
43、)不會出錯,但語句不易理解;a | b < c & d = a | (b < c) & d,(3)造成了判斷條件出錯。4.2 使用有意義的標識,避免直接使用數(shù)字避免使用不易理解的數(shù)字,用有意義的標識來替代。涉及物理狀態(tài)或者含有物理意義的常量,不應直接使用數(shù)字,必須用有意義的枚舉或宏來代替。示例:如下的程序可讀性差。if (Trunkindex.trunk_state = 0)Trunkindex.trunk_state = 1;. / program code應改為如下形式。#define TRUNK_IDLE 0#define TRUNK_BUSY 1if (Tr
44、unkindex.trunk_state = TRUNK_IDLE)Trunkindex.trunk_state = TRUNK_BUSY;. / program code4.3 源程序中關系較為緊密的代碼應盡可能相鄰這樣做的好處是便于程序閱讀和查找。示例:以下代碼布局不太合理。rect.length = 10;char_poi = str;rect.width = 5;若按如下形式書寫,可能更清晰一些。rect.length = 10;rect.width = 5; / 矩形的長與寬關系較密切,放在一起。char_poi = str;4.4 不要使用難懂的技巧性很高的語句、復雜的表達式除非很
45、有必要時,原則上不要使用難懂的技巧性很高的語句和復雜的表達式高技巧語句不等于高效率的程序,源程序占用空間的節(jié)約并不等于目標程序占用空間的節(jié)約,實際上程序的效率關鍵在于算法。(1)如下表達式,考慮不周就可能出問題,也較難理解。* stat_poi + += 1;* + stat_poi += 1;應分別改為如下:*stat_poi += 1;stat_poi+; / 此二語句功能相當于“ * stat_poi + += 1; ”+ stat_poi;*stat_poi += 1; / 此二語句功能相當于“ * + stat_poi += 1; ”(2)如下表達式,不同的編譯器給出的結果不一樣,b
46、i是否先執(zhí)行?x=bi + i+;應改為:x = bi + i;i+;5 變量與結構5.1 謹慎使用全局(公共)變量(1)去掉沒必要的公共變量。公共變量是增大模塊間耦合的原因之一,故應減少沒必要的公共變量以降低模塊間的耦合度。(2)仔細定義并明確公共變量的含義、作用、取值范圍及公共變量間的關系。在對變量聲明的同時,應對其含義、作用及取值范圍進行注釋說明,同時若有必要還應說明與其它變量的關系。(3)防止局部變量與公共變量同名通過使用較好的命名規(guī)則來消除此問題。5.2 數(shù)據(jù)類型間的轉換(1)編程時,要注意數(shù)據(jù)類型的強制轉換。當進行數(shù)據(jù)類型強制轉換時,其數(shù)據(jù)的意義、轉換后的取值等都有可能發(fā)生變化,而
47、這些細節(jié)若考慮不周,就很有可能留下隱患。(2)對編譯系統(tǒng)默認的數(shù)據(jù)類型轉換,也要有充分的認識。示例:如下賦值,多數(shù)編譯器不產生告警,但值的含義還是稍有變化。char chr;unsigned short int exam;chr = -1;exam = chr; / 編譯器不產生告警,此時exam為0xFFFF。(3)盡量減少沒有必要的數(shù)據(jù)類型默認轉換與強制轉換。例如,所有的 unsigned類型都應該有后綴“U”以明確其類型。(4)合理地設計數(shù)據(jù)并使用自定義數(shù)據(jù)類型,避免數(shù)據(jù)間進行不必要的類型轉換。(5)對自定義數(shù)據(jù)類型進行恰當命名,使它成為自描述性的,以提高代碼可讀性。注意其命名方式在同一
48、產品中的統(tǒng)一,并且保證沒有多重定義。使用自定義類型,可以彌補編程語言提供類型少、信息量不足的缺點,并能使程序清晰、簡潔。示例:可參考如下方式聲明自定義數(shù)據(jù)類型。下面的聲明可使數(shù)據(jù)類型的使用簡潔、明了。typedef unsigned char BYTE;typedef unsigned short WORD;typedef unsigned int DWORD;下面的聲明可使數(shù)據(jù)類型具有更豐富的含義。typedef float DISTANCE;typedef float SCORE;(6)不要用八進制數(shù)整型常數(shù)以”0“開始會被認為是8進制。示例:code1=109code2=100code3
49、=052code4=071如果是對總線消息初始化,會有危險。6 函數(shù)與過程6.1 函數(shù)的功能與規(guī)模設計(1)函數(shù)應當短而精美,而且只做一件事。不要設計多用途面面俱到的函數(shù),多功能集于一身的函數(shù),很可能使函數(shù)的理解、測試、維護等變得困難。 一個函數(shù)應最多占滿1或2個屏幕(就象我們知道的那樣,ISO/ANSI的屏幕大小是80X24),只做一件事并且把它做好。一個函數(shù)的最大長度與它的復雜度和縮進級別成反比。所以,如果如果你有一個概念上簡單(案,“簡單”是simple而不是easy)的函數(shù),它恰恰包含著一個很長的case語句,這樣你不得不為不同的情況準備不懂的處理,那么這樣的長函數(shù)是沒問題的。然而,如
50、果你有一個復雜的函數(shù),你猜想一個并非天才的高一學生可能看不懂得這個函數(shù),你就應當努力把它減縮得更接近前面提到的最大函數(shù)長度限制??梢允褂靡恍┹o助函數(shù),給它們取描述性的名字(如果你認為這些輔助函數(shù)的調用是性能關鍵的,可以讓編譯器把它們內聯(lián)進來,這比在單個函數(shù)內完成所有的事情通常要好些)。對函數(shù)還存在另一個測量標準:局部變量的數(shù)目。這不該超過5到10個,否則你可能會弄錯。應當重新考慮這個函數(shù),把它分解成小片。人類的大腦一般能同時記住7個不同的東西,超過這個數(shù)目就會犯糊涂?;蛟S你認為自己很聰明,那么請你理解一下從現(xiàn)在開始的2周時間你都做什么了。(2)為簡單功能編寫函數(shù)。雖然為僅用一兩行就可完成的功能
51、去編函數(shù)好象沒有必要,但用函數(shù)可使功能明確化,增加程序可讀性,亦可方便維護、測試。 示例:如下語句的功能不很明顯。value = ( a > b ) ? a : b ;改為如下就很清晰了。int max (int a, int b)return (a > b) ? a : b);value = max (a, b);或改為如下。#define MAX (a, b) (a) > (b) ? (a) : (b)value = MAX (a, b);當一個過程(函數(shù))中對較長變量(一般是結構的成員)有較多引用時,可以用一個意義相當?shù)暮甏孢@樣可以增加編程效率和程序的可讀性。 示例:
52、在某過程中較多引用TheReceiveBufferFirstSocket.byDataPtr,則可以通過以下宏定義來代替:# define pSOCKDATA TheReceiveBufferFirstScoket.byDataPtr(3)防止把沒有關聯(lián)的語句放到一個函數(shù)中,防止函數(shù)或過程內出現(xiàn)隨機內聚。隨機內聚是指將沒有關聯(lián)或關聯(lián)很弱的語句放到同一個函數(shù)或過程中。隨機內聚給函數(shù)或過程的維護、測試及以后的升級等造成了不便,同時也使函數(shù)或過程的功能不明確。使用隨機內聚函數(shù),常常容易出現(xiàn)在一種應用場合需要改進此函數(shù),而另一種應用場合又不允許這種改進,從而陷入困境。在編程時,經常遇到在不同函數(shù)中使用
53、相同的代碼,許多開發(fā)人員都愿把這些代碼提出來,并構成一個新函數(shù)。若這些代碼關聯(lián)較大并且是完成一個功能的,那么這種構造是合理的,否則這種構造將產生隨機內聚的函數(shù)。示例:如下函數(shù)就是一種隨機內聚。void Init_Var( void )Rect.length = 0;Rect.width = 0; /* 初始化矩形的長與寬 */Point.x = 10;Point.y = 10; /* 初始化“點”的坐標 */矩形的長、寬與點的坐標基本沒有任何關系,故以上函數(shù)是隨機內聚。應如下分為兩個函數(shù):void Init_Rect( void )Rect.length = 0;Rect.width = 0;
54、 /* 初始化矩形的長與寬 */void Init_Point( void )Point.x = 10;Point.y = 10; /* 初始化“點”的坐標 */(4)如果多段代碼重復做同一件事情,那么在函數(shù)的劃分上可能存在問題。若此段代碼各語句之間有實質性關聯(lián)并且是完成同一件功能的,那么可考慮把此段代碼構造成一個新的函數(shù)。(5)減少函數(shù)本身或函數(shù)間的遞歸調用。遞歸調用特別是函數(shù)間的遞歸調用(如A->B->C->A),影響程序的可理解性;遞歸調用一般都占用較多的系統(tǒng)資源(如??臻g);遞歸調用對程序的測試有一定影響。故除非為某些算法或功能的實現(xiàn)方便,應減少沒必要的遞歸調用,對于
55、safe-related 系統(tǒng)不能用遞歸,因為超出堆??臻g很危險。6.2 函數(shù)的返回值(1)對于函數(shù)的返回位置,盡量保持單一性,即一個函數(shù)盡量做到只有一個返回位置。(單入口單出口)。要求大家統(tǒng)一函數(shù)的返回值,所有的函數(shù)的返回值都將以編碼的方式返回。例如編碼定義如下:#define CM_POINT_IS_NULL CMMAKEHR(0X200):建議函數(shù)實現(xiàn)如下:LONG 函數(shù)名(參數(shù),)LONG lResult; /保持錯誤號lResult=CM_OK;/如果參數(shù)有錯誤則返回錯誤號if(參數(shù)=NULL)lResult=CM_POINT_IS_NULL;goto END;END:return lResult;(2)除非必要,最好不要把與函數(shù)返回值類型不同的變量,以編譯系統(tǒng)默認的轉換方式或強制的轉換方式作為返回值返回。(3)函數(shù)的返回值要清楚、明了,讓使用者不容易忽視錯誤情況。函數(shù)的每種出錯返回值的意義要清晰、明了、準確,防止
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 【正版授權】 IEC TS 63576:2025 EN Evaluation methods for protection against risk of fire in electric tumble dryers
- 【正版授權】 IEC 62290-3:2025 EN-FR Railway applications - Urban guided transport management and command/control systems - Part 3: System requirements specification
- 【正版授權】 IEC 62899-401:2025 EN Printed electronics - Part 401: Printability - Overview
- 2025年應急管理與領導力考試試題及答案
- 2025年智能制造與工業(yè)互聯(lián)網(wǎng)試卷及答案
- 2025年戰(zhàn)略管理考試試題及答案
- 2025年藝術管理職資格考試試題及答案
- 2025年現(xiàn)代漢語語法與用法考試試題及答案
- 2025年人機交互設計職業(yè)能力考試試題及答案
- 2025年成人教育法相關知識考試試題及答案
- 《融媒體實務》教學課件(全)
- 從deepfakes深度偽造技術看AI安全
- 中小企業(yè)的網(wǎng)絡組建局域網(wǎng)的組建網(wǎng)絡的組建與規(guī)劃網(wǎng)絡結構拓撲圖
- 攻絲扭矩計算
- 天津保利物業(yè)供貨合同范本
- 能源中國學習通課后章節(jié)答案期末考試題庫2023年
- 初中數(shù)學一題多解
- 退役軍人事務局一體化平臺解決方案
- 2023年中小學生籃球比賽報名表
- 體育管理學完整版
- 手語操比賽方案
評論
0/150
提交評論