華為代碼規(guī)范_第1頁
華為代碼規(guī)范_第2頁
華為代碼規(guī)范_第3頁
華為代碼規(guī)范_第4頁
華為代碼規(guī)范_第5頁
已閱讀5頁,還剩84頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

(完整word版)華為代碼規(guī)范(完整word版)華為代碼規(guī)范第89頁共89頁(完整word版)華為代碼規(guī)范華為代碼規(guī)范

目錄TOC\o"1-2"\u1 概述 51.1 編寫目的 51.2 文檔約定 51.3 預期的讀者和閱讀建議 51.4 參考文獻 52 排版要求 52.1 程序塊縮進 52.2 程序塊之間空行 52.3 長語句和長表達式 62.4 循環(huán)、判斷等長表達式或語句 72.5 長參數 72.6 短語句 82.7 條件、循環(huán)語句 82.8 語句對齊 82.9 函數、過程和結構等語句塊 92.10 程序塊分界符 92.11 操作符前后空格 102.12 其他 113 注釋 113.1 有效注釋量 113.2 公司標識 113.3 說明性文件 123.4 源文件頭 133.5 函數頭部說明 133.6 注釋與代碼一致 143.7 注釋內容 143.8 注釋縮寫 143.9 注釋位置 143.10 變量、常量注釋 153.11 數據結構的注釋 153.12 全局變量 163.13 注釋縮排 163.14 注釋與代碼之間空行 173.15 變量定義、分支語句 173.16 其他 194 標識符命名 204.1 命名清晰 204.2 特殊命名需注釋 214.3 命名風格保持一致 214.4 變量命名 214.5 命名規(guī)范與系統(tǒng)風格一致 214.6 其他 225 可讀性 235.1 運算符優(yōu)先級 235.2 避免直接使用數字作為標識符 235.3 其他 246 變量、結構 256.1 公共變量 256.2 公共變量說明 256.3 公共變量訪問說明 256.4 公共變量賦值 266.5 防止局部變量與公共變量同名。 266.6 嚴禁使用未經初始化的變量作為右值。 266.7 其他 267 函數、過程 347.1 對所調用函數的錯誤返回碼要仔細、全面地處理。 347.2 明確函數功能,精確(而不是近似)地實現函數設計。 347.3 局部變量 347.4 全局變量 347.5 接口函數參數 357.6 其他 358 可測性 448.1 調測開關 448.2 打印信息 458.3 單元測試 458.4 集成測試 458.5 斷言使用 458.6 設置與取消有關測試手段時,不能影響軟件功能功能 488.7 版本維護 488.8 其他 489 程序效率 509.1 編程時要經常注意代碼的效率。 509.2 提高代碼效率 509.3 全局效率高于局部效率 519.4 提高代碼空間效率 519.5 循環(huán)體內工作量最小化 529.6 其他 5310 質量保證 5610.1 在軟件設計過程中構筑軟件質量。 5610.2 代碼質量保證優(yōu)先原則 5610.3 只引用屬于自己的存貯空間。 5610.4 防止引用已經釋放的內存空間。 5610.5 內存及時釋放 5710.6 文件句柄及時關閉 5710.7 防止內存操作越界 5810.8 認真處理程序所能遇到的各種出錯情況 5910.9 初始化變量 5910.10 數據一致性檢查 5910.11 嚴禁隨意更改其它模塊或系統(tǒng)的有關設置和配置 5910.12 不能隨意改變與其它模塊的接口 5910.13 系統(tǒng)接口 5910.14 編程時,要防止差1錯誤 6110.15 操作符檢查 6110.16 分支語句寫完整 6210.17 使用return語句 6210.18 不要濫用goto語句 6210.19 其他 6211 代碼編輯、編譯、審查 6511.1 打開編譯器的所有告警開關對程序進行編譯 6511.2 在產品軟件(項目組)中,要統(tǒng)一編譯開關選項 6511.3 通過代碼走讀及審查方式對代碼進行檢查。 6511.4 測試部測試產品之前,應對代碼進行抽查及評審 6511.5 其他 6512 代碼測試、維護 6712.1 單元測試要求至少達到語句覆蓋 6712.2 單元測試開始要跟蹤每一條語句,并觀察數據流及變量的變化 6712.3 清理、整理或優(yōu)化后的代碼要經過審查及測試。 6712.4 代碼版本升級要經過嚴格測試 6712.5 使用工具軟件對代碼版本進行維護 6712.6 正式版本上軟件的任何修改都應有詳細的文檔記錄 6712.7 其他 6713 宏 6813.1 用宏定義表達式時,要使用完備的括號 6813.2 將宏所定義的多條表達式放在大括號中 6813.3 使用宏時,不允許參數發(fā)生變化 69概述編寫目的為規(guī)范軟件開發(fā)人員的代碼編寫提供參考依據和統(tǒng)一標準。文檔約定說明本文檔中所用到的專用術語定義或解釋,縮略詞定義。預期的讀者和閱讀建議本文檔適用于所有軟件開發(fā)人員。參考文獻列出有關的參考文件,如:

a.屬于本項目的其他已發(fā)表文件;

b.本文件中各處引用的文檔資料。列出這些文件的標題、作者,說明能夠得到這些文件資料的來源。排版要求程序塊縮進程序塊要采用縮進風格編寫,縮進的空格數為4個。說明:對于由開發(fā)工具自動生成的代碼可以有不一致。程序塊之間空行相對獨立的程序塊之間、變量說明之后必須加空行。示例:如下例子不符合規(guī)范。if(!valid_ni(ni)){...//programcode}repssn_ind=ssn_data[index].repssn_index;repssn_ni=ssn_data[index].ni;應如下書寫if(!valid_ni(ni)){...//programcode}repssn_ind=ssn_data[index].repssn_index;repssn_ni=ssn_data[index].ni;長語句和長表達式較長的語句(>80字符)要分成多行書寫,長表達式要在低優(yōu)先級操作符處劃分新行,操作符放在新行之首,劃分出的新行要進行適當的縮進,使排版整齊,語句可讀。示例:perm_count_msg.head.len=NO7_TO_STAT_PERM_COUNT_LEN+STAT_SIZE_PER_FRAM*sizeof(_UL);act_task_table[frame_id*STAT_TASK_CHECK_NUMBER+index].occupied=stat_poi[index].occupied;act_task_table[taskno].duration_true_or_false=SYS_get_sccp_statistic_state(stat_item);report_or_not_flag=((taskno<MAX_ACT_TASK_NUMBER)&&(n7stat_stat_item_valid(stat_item))&&(act_task_table[taskno].result_data!=0));循環(huán)、判斷等長表達式或語句循環(huán)、判斷等語句中若有較長的表達式或語句,則要進行適應的劃分,長表達式要在低優(yōu)先級操作符處劃分新行,操作符放在新行之首。示例:if((taskno<max_act_task_number)&&(n7stat_stat_item_valid(stat_item))){...//programcode}for(i=0,j=0;(i<BufferKeyword[word_index].word_length)&&(j<NewKeyword.word_length);i++,j++){...//programcode}for(i=0,j=0;(i<first_word_length)&&(j<second_word_length);i++,j++){...//programcode}長參數若函數或過程中的參數較長,則要進行適當的劃分。示例:n7stat_str_compare((BYTE*)&stat_object,(BYTE*)&(act_task_table[taskno].stat_object),sizeof(_STAT_OBJECT));n7stat_flash_act_duration(stat_item,frame_id*STAT_TASK_CHECK_NUMBER+index,stat_object);短語句不允許把多個短語句寫在一行中,即一行只寫一條語句。示例:如下例子不符合規(guī)范。rect.length=0;rect.width=0;應如下書寫rect.length=0;rect.width=0;條件、循環(huán)語句if、for、do、while、case、switch、default等語句自占一行,且if、for、do、while等語句的執(zhí)行語句部分無論多少都要加括號{}。示例:如下例子不符合規(guī)范。if(pUserCR==NULL)return;應如下書寫:if(pUserCR==NULL){return;}語句對齊對齊只使用空格鍵,不使用TAB鍵。說明:以免用不同的編輯器閱讀程序時,因TAB鍵所設置的空格數目不同而造成程序布局不整齊,不要使用BC作為編輯器合版本,因為BC會自動將8個空格變?yōu)橐粋€TAB鍵,因此使用BC合入的版本大多會將縮進變亂。函數、過程和結構等語句塊函數或過程的開始、結構的定義及循環(huán)、判斷等語句中的代碼都要采用縮進風格,case語句下的情況處理語句也要遵從語句縮進要求。程序塊分界符程序塊的分界符(如C/C++語言的大括號‘{’和‘}’)應各獨占一行并且位于同一列,同時與引用它們的語句左對齊。在函數體的開始、類的定義、結構的定義、枚舉的定義以及if、for、do、while、switch、case語句中的程序都要采用如上的縮進方式。示例:如下例子不符合規(guī)范。for(...){...//programcode}if(...){...//programcode}voidexample_fun(void){...//programcode}應如下書寫。for(...){...//programcode}if(...){...//programcode}voidexample_fun(void){...//programcode}操作符前后空格在兩個以上的關鍵字、變量、常量進行對等操作時,它們之間的操作符之前、之后或者前后要加空格;進行非對等操作時,如果是關系密切的立即操作符(如->),后不應加空格。說明:采用這種松散方式編寫代碼的目的是使代碼更加清晰。由于留空格所產生的清晰性是相對的,所以,在已經非常清晰的語句中沒有必要再留空格,如果語句已足夠清晰則括號內側(即左括號后面和右括號前面)不需要加空格,多重括號間不必加空格,因為在C/C++語言中括號已經是最清晰的標志了。在長語句中,如果需要加的空格非常多,那么應該保持整體清晰,而在局部不加空格。給操作符留空格時不要連續(xù)留兩個以上空格。示例:(1)逗號、分號只在后面加空格。inta,b,c;(2)比較操作符,賦值操作符"="、"+=",算術操作符"+"、"%",邏輯操作符"&&"、"&",位域操作符"<<"、"^"等雙目操作符的前后加空格。if(current_time>=MAX_TIME_VALUE)a=b+c;a*=2;a=b^2;(3)"!"、"~"、"++"、"--"、"&"(地址運算符)等單目操作符前后不加空格。*p='a';//內容操作"*"與內容之間flag=!isEmpty;//非操作"!"與內容之間p=&mem;//地址操作"&"與內容之間i++;//"++","--"與內容之間(4)"->"、"."前后不加空格。p->id=pid;//"->"指針前后不加空格(5)if、for、while、switch等與后面的括號間應加空格,使if等關鍵字更為突出、明顯。if(a>=b&&c>d)其他一行程序以小于80字符為宜,不要寫得過長。注釋有效注釋量一般情況下,源程序有效注釋量必須在20%以上。說明:注釋的原則是有助于對程序的閱讀理解,在該加的地方都加了,注釋不宜太多也不能太少,注釋語言必須準確、易懂、簡潔。公司標識在頭文件中加入公司標識。示例如下:**************************************************************************/

/*

*/

/*Copyright(c)1996-1998

XXXXXXCompany

*/

/*

xxxxxxxx

版權所有1996-1998

*/

/*

*/

/*PROPRIETARYRIGHTSof

XXXXXXCompany

areinvolvedinthe

*/

/*subject

matterofthismaterial.

Allmanufacturing,reproduction,use,*/

/*and

salesrightspertainingtothissubjectmatteraregovernedbythe

*/

/*licenseagreement.

Therecipientofthissoftwareimplicitlyaccepts*/

/*thetermsofthelicense.

*/

/*本軟件文檔資料是xxx公司的資產,任何人士閱讀和使用本資料必須獲得

*/

/*相應的書面授權,承擔保密責任和接受相應的法律約束.

*/

/*

*/

/**************************************************************************/說明性文件說明性文件(如頭文件.h文件、.inc文件、.def文件、編譯說明文件.cfg等)頭部應進行注釋,注釋必須列出:版權說明、版本號、生成日期、作者、內容、功能、與其它文件的關系、修改日志等,頭文件的注釋中還應有函數功能簡要說明。示例:下面這段頭文件的頭注釋比較標準,當然,并不局限于此格式,但上述信息建議要包含在內。/*************************************************Copyright(C),1996-1998,xxxxx.Co.,Ltd.Filename://文件名Author:Version:Date://作者、版本及完成日期Description://用于詳細說明此程序文件完成的主要功能,與其他模塊//或函數的接口,輸出值、取值范圍、含義及參數間的控//制、順序、獨立或依賴等關系Others://其它內容的說明FunctionList://主要函數列表,每條記錄應包括函數名及功能簡要說明1.History://修改歷史記錄列表,每條修改記錄應包括修改日期、修改//者及修改內容簡述1.Date:Author:Modification:2....*************************************************/源文件頭源文件頭部應進行注釋,列出:版權說明、版本號、生成日期、作者、模塊目的/功能、主要函數及其功能、修改日志等。示例:下面這段源文件的頭注釋比較標準,當然,并不局限于此格式,但上述信息建議要包含在內。/************************************************************Copyright(C),1988-1999,XxxxxxTech.Co.,Ltd.FileName:test.cppAuthor:Version:Date:Description://模塊描述Version://版本信息FunctionList://主要函數及其功能1.History://歷史修改記錄<author><time><version><desc>David96/10/121.0buildthismoudle***********************************************************/說明:Description一項描述本文件的內容、功能、內部各部分之間的關系及本文件與其它文件關系等。History是修改歷史記錄列表,每條修改記錄應包括修改日期、修改者及修改內容簡述。函數頭部說明函數頭部應進行注釋,列出:函數的目的/功能、輸入參數、輸出參數、返回值、調用關系(函數、表)等。示例:下面這段函數的注釋比較標準,當然,并不局限于此格式,但上述信息建議要包含在內。/*************************************************Function://函數名稱Description://函數功能、性能等的描述Calls://被本函數調用的函數清單CalledBy://調用本函數的函數清單TableAccessed://被訪問的表(此項僅對于牽扯到數據庫操作的程序)TableUpdated://被修改的表(此項僅對于牽扯到數據庫操作的程序)Input://輸入參數說明,包括每個參數的作//用、取值說明及參數間關系。Output://對輸出參數的說明。Return://函數返回值的說明Others://其它說明*************************************************/注釋與代碼一致邊寫代碼邊注釋,修改代碼同時修改相應的注釋,以保證注釋與代碼的一致性。不再有用的注釋要刪除。注釋內容注釋的內容要清楚、明了,含義準確,防止注釋二義性。說明:錯誤的注釋不但無益反而有害。注釋縮寫避免在注釋中使用縮寫。說明:在使用縮寫時或之前,應對縮寫進行必要的說明。注釋位置注釋應與其描述的代碼相近,對代碼的注釋應放在其上方或右方(對單條語句的注釋)相鄰位置,不可放在下面,如放于上方則需與其上面的代碼用空行隔開。示例:如下例子不符合規(guī)范。例1:/*getreplicatesubsystemindexandnetindicator*/repssn_ind=ssn_data[index].repssn_index;repssn_ni=ssn_data[index].ni;例2:repssn_ind=ssn_data[index].repssn_index;repssn_ni=ssn_data[index].ni;/*getreplicatesubsystemindexandnetindicator*/應如下書寫/*getreplicatesubsystemindexandnetindicator*/repssn_ind=ssn_data[index].repssn_index;repssn_ni=ssn_data[index].ni;變量、常量注釋對于所有有物理含義的變量、常量,如果其命名不是充分自注釋的,在聲明時都必須加以注釋,說明其物理含義。變量、常量、宏的注釋應放在其上方相鄰位置或右方。示例:/*activestatistictasknumber*/#defineMAX_ACT_TASK_NUMBER1000#defineMAX_ACT_TASK_NUMBER1000/*activestatistictasknumber*/數據結構的注釋數據結構聲明(包括數組、結構、類、枚舉等),如果其命名不是充分自注釋的,必須加以注釋。對數據結構的注釋應放在其上方相鄰位置,不可放在下面;對結構中的每個域的注釋放在此域的右方。示例:可按如下形式說明枚舉/數據/聯合結構。/*sccpinterfacewithsccpuserprimitivemessagename*/enumSCCP_USER_PRIMITIVE{N_UNITDATA_IND,/*sccpnotifysccpuserunitdatacome*/N_NOTICE_IND,/*sccpnotifyusertheNo.7networkcannot*//*transmissionthismessage*/N_UNITDATA_REQ,/*sccpuser'sunitdatatransmissionrequest*/};全局變量全局變量要有較詳細的注釋,包括對其功能、取值范圍、哪些函數或過程存取它以及存取時注意事項等的說明。示例:/*TheErrorCodewhenSCCPtranslate*//*GlobalTitlefailure,asfollows*///變量作用、含義/*0-SUCCESS1-GTTableerror*//*2-GTerrorOthers-nouse*///變量取值范圍/*onlyfunctionSCCPTranslate()in*//*thismodualcanmodifyit,andother*//*modulecanvisititthroughcall*//*thefunctionGetGTTransErrorCode()*///使用方法BYTEg_GTTranErrorCode;注釋縮排注釋與所描述內容進行同樣的縮排。說明:可使程序排版整齊,并方便注釋的閱讀與理解。示例:如下例子,排版不整齊,閱讀稍感不方便。voidexample_fun(void){/*codeonecomments*/CodeBlockOne/*codetwocomments*/CodeBlockTwo}應改為如下布局。voidexample_fun(void){/*codeonecomments*/CodeBlockOne/*codetwocomments*/CodeBlockTwo}注釋與代碼之間空行將注釋與其上面的代碼用空行隔開。示例:如下例子,顯得代碼過于緊湊。/*codeonecomments*/programcodeone/*codetwocomments*/programcodetwo應如下書寫/*codeonecomments*/programcodeone/*codetwocomments*/programcodetwo變量定義、分支語句對變量的定義和分支語句(條件分支、循環(huán)語句等)必須編寫注釋。說明:這些語句往往是程序實現某一特定功能的關鍵,對于維護人員來說,良好的注釋幫助更好的理解程序,有時甚至優(yōu)于看設計文檔。示例(注意斜體加粗部分):caseCMD_UP:ProcessUp();break;caseCMD_DOWN:ProcessDown();break;caseCMD_FWD:ProcessFwd();if(...){...break;}else{ProcessCFW_B();//nowjumpintocaseCMD_A}caseCMD_A:ProcessA();break;caseCMD_B:ProcessB();break;caseCMD_C:ProcessC(); break;caseCMD_D:ProcessD();break;...其他避免在一行代碼或表達式的中間插入注釋。說明:除非必要,不應在代碼或表達中間插入注釋,否則容易使代碼可理解性變差。通過對函數或過程、變量、結構等正確的命名以及合理地組織代碼的結構,使代碼成為自注釋的。說明:清晰準確的函數、變量等的命名,可增加代碼可讀性,并減少不必要的注釋。在代碼的功能、意圖層次上進行注釋,提供有用、額外的信息。說明:注釋的目的是解釋代碼的目的、功能和采用的方法,提供代碼以外的信息,幫助讀者理解代碼,防止沒必要的重復注釋信息。示例:如下注釋意義不大。/*ifreceive_flagisTRUE*/if(receive_flag)而如下的注釋則給出了額外有用的信息。/*ifmtpreceiveamessagefromlinks*/if(receive_flag)在程序塊的結束行右方加注釋標記,以表明某程序塊的結束。說明:當代碼段較長,特別是多重嵌套時,這樣做可以使代碼更清晰,更便于閱讀。示例:參見如下例子。if(...){//programcodewhile(index<MAX_INDEX){//programcode}/*endofwhile(index<MAX_INDEX)*///指明該條while語句結束}/*endofif(...)*///指明是哪條if語句結束注釋格式盡量統(tǒng)一,建議使用“/*……*/”。注釋應考慮程序易讀及外觀排版的因素,使用的語言若是中、英兼有的,建議多使用中文,除非能用非常流利準確的英文表達。說明:注釋語言不統(tǒng)一,影響程序易讀性和外觀排版,出于對維護人員的考慮,建議使用中文。標識符命名命名清晰標識符的命名要清晰、明了,有明確含義,同時使用完整的單詞或大家基本可以理解的縮寫,避免使人產生誤解。說明:較短的單詞可通過去掉“元音”形成縮寫;較長的單詞可取單詞的頭幾個字母形成縮寫;一些單詞有大家公認的縮寫。示例:如下單詞的縮寫能夠被大家基本認可。temp可縮寫為tmp;flag可縮寫為flg;statistic可縮寫為stat;increment可縮寫為inc;message可縮寫為msg;特殊命名需注釋命名中若使用特殊約定或縮寫,則要有注釋說明。說明:應該在源文件的開始之處,對文件中所使用的縮寫或約定,特別是特殊的縮寫,進行必要的注釋說明。命名風格保持一致自己特有的命名風格,要自始至終保持一致,不可來回變化。說明:個人的命名風格,在符合所在項目組或產品組的命名規(guī)則的前提下,才可使用。(即命名規(guī)則中沒有規(guī)定到的地方才可有個人命名風格)。變量命名對于變量命名,禁止取單個字符(如i、j、k...),建議除了要有具體含義外,還能表明其變量類型、數據類型等,但i、j、k作局部循環(huán)變量是允許的。說明:變量,尤其是局部變量,如果用單個字符表示,很容易敲錯(如i寫成j),而編譯時又檢查不出來,有可能為了這個小小的錯誤而花費大量的查錯時間。示例:下面所示的局部變量名的定義方法可以借鑒。intliv_Width其變量名解釋如下: l局部變量(Local)(其它:g全局變量(Global)...) i數據類型(Interger) v變量(Variable)(其它:c常量(Const)...) Width變量含義這樣可以防止局部變量與全局變量重名。命名規(guī)范與系統(tǒng)風格一致命名規(guī)范必須與所使用的系統(tǒng)風格保持一致,并在同一項目中統(tǒng)一,比如采用UNIX的全小寫加下劃線的風格或大小寫混排的方式,不要使用大小寫與下劃線混排的方式,用作特殊標識如標識成員變量或全局變量的m_和g_,其后加上大小寫混排的方式是允許的。示例:Add_User不允許,add_user、AddUser、m_AddUser允許。其他除非必要,不要用數字或較奇怪的字符來定義標識符。示例:如下命名,使人產生疑惑。#define_EXAMPLE_0_TEST_#define_EXAMPLE_1_TEST_voidset_sls00(BYTEsls);應改為有意義的單詞命名#define_EXAMPLE_UNIT_TEST_#define_EXAMPLE_ASSERT_TEST_voidset_udt_msg_sls(BYTEsls);在同一軟件產品內,應規(guī)劃好接口部分標識符(變量、結構、函數及常量)的命名,防止編譯、鏈接時產生沖突。說明:對接口部分的標識符應該有更嚴格限制,防止沖突。如可規(guī)定接口部分的變量與常量之前加上“模塊”標識等。用正確的反義詞組命名具有互斥意義的變量或相反動作的函數等。說明:下面是一些在軟件中常用的反義詞組。add/removebegin/endcreate/destroyinsert/deletefirst/lastget/releaseincrement/decrementput/getadd/deletelock/unlockopen/closemin/maxold/newstart/stopnext/previoussource/targetshow/hidesend/receivesource/destinationcut/pasteup/down示例:intmin_sum;intmax_sum;intadd_user(BYTE*user_name);intdelete_user(BYTE*user_name);3.6.4除了編譯開關/頭文件等特殊應用,應避免使用_EXAMPLE_TEST_可讀性運算符優(yōu)先級注意運算符的優(yōu)先級,并用括號明確表達式的操作順序,避免使用默認優(yōu)先級。說明:防止閱讀程序時產生誤解,防止因默認的優(yōu)先級與設計思想不符而導致程序出錯。示例:下列語句中的表達式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)不會出錯,但語句不易理解;a|b<c&d=a|(b<c)&d,(3)造成了判斷條件出錯。避免直接使用數字作為標識符避免使用不易理解的數字,用有意義的標識來替代。涉及物理狀態(tài)或者含有物理意義的常量,不應直接使用數字,必須用有意義的枚舉或宏來代替。示例:如下的程序可讀性差。if(Trunk[index].trunk_state==0){Trunk[index].trunk_state=1;...//programcode}應改為如下形式。#defineTRUNK_IDLE0#defineTRUNK_BUSY1if(Trunk[index].trunk_state==TRUNK_IDLE){Trunk[index].trunk_state=TRUNK_BUSY;...//programcode}其他源程序中關系較為緊密的代碼應盡可能相鄰。說明:便于程序閱讀和查找。示例:以下代碼布局不太合理。rect.length=10;char_poi=str;rect.width=5;若按如下形式書寫,可能更清晰一些。rect.length=10;rect.width=5;//矩形的長與寬關系較密切,放在一起。char_poi=str;不要使用難懂的技巧性很高的語句,除非很有必要時。說明:高技巧語句不等于高效率的程序,實際上程序的效率關鍵在于算法。示例:如下表達式,考慮不周就可能出問題,也較難理解。*stat_poi+++=1;*++stat_poi+=1;應分別改為如下。*stat_poi+=1;stat_poi++;//此二語句功能相當于“*stat_poi+++=1;”++stat_poi;*stat_poi+=1;//此二語句功能相當于“*++stat_poi+=1;變量、結構公共變量去掉沒必要的公共變量。說明:公共變量是增大模塊間耦合的原因之一,故應減少沒必要的公共變量以降低模塊間的耦合度。公共變量說明仔細定義并明確公共變量的含義、作用、取值范圍及公共變量間的關系。說明:在對變量聲明的同時,應對其含義、作用及取值范圍進行注釋說明,同時若有必要還應說明與其它變量的關系。公共變量訪問說明明確公共變量與操作此公共變量的函數或過程的關系,如訪問、修改及創(chuàng)建等。說明:明確過程操作變量的關系后,將有利于程序的進一步優(yōu)化、單元測試、系統(tǒng)聯調以及代碼維護等。這種關系的說明可在注釋或文檔中描述。示例:在源文件中,可按如下注釋形式說明。RELATIONSystem_InitInput_RecPrint_RecStat_ScoreStudentCreateModifyAccessAccessScoreCreateModifyAccessAccess,Modify注:RELATION為操作關系;System_Init、Input_Rec、Print_Rec、Stat_Score為四個不同的函數;Student、Score為兩個全局變量;Create表示創(chuàng)建,Modify表示修改,Access表示訪問。其中,函數Input_Rec、Stat_Score都可修改變量Score,故此變量將引起函數間較大的耦合,并可能增加代碼測試、維護的難度。公共變量賦值當向公共變量傳遞數據時,要十分小心,防止賦與不合理的值或越界等現象發(fā)生。說明:對公共變量賦值時,若有必要應進行合法性檢查,以提高代碼的可靠性、穩(wěn)定性。防止局部變量與公共變量同名。說明:若使用了較好的命名規(guī)則,那么此問題可自動消除。嚴禁使用未經初始化的變量作為右值。說明:特別是在C/C++中引用未經賦值的指針,經常會引起系統(tǒng)崩潰。其他防止多個模塊共用公共變量構造僅有一個模塊或函數可以修改、創(chuàng)建,而其余有關模塊或函數只訪問的公共變量,防止多個不同模塊或函數都可以修改、創(chuàng)建同一公共變量的現象。說明:降低公共變量耦合度。數據類型使用嚴格形式定義的、可移植的數據類型,盡量不要使用與具體硬件或軟件環(huán)境關系密切的變量。說明:使用標準的數據類型,有利于程序的移植。示例:如下例子(在DOS下BC3.1環(huán)境中),在移植時可能產生問題。voidmain(){registerintindex;//寄存器變量_AX=0x4000;//_AX是BC3.1提供的寄存器“偽變量”...//programcode}結構結構的功能要單一,是針對一種事務的抽象。說明:設計結構時應力爭使結構代表一種現實事務的抽象,而不是同時代表多種。結構中的各元素應代表同一事務的不同側面,而不應把描述沒有關系或關系很弱的不同事務的元素放到同一結構中。示例:如下結構不太清晰、合理。typedefstructSTUDENT_STRU{unsignedcharname[8];/*student'sname*/unsignedcharage;/*student'sage*/unsignedcharsex;/*student'ssex,asfollows*//*0-FEMALE;1-MALE*/unsignedcharteacher_name[8];/*thestudentteacher'sname*/unisgnedcharteacher_sex;/*histeachersex*/}STUDENT;若改為如下,可能更合理些。typedefstructTEACHER_STRU{unsignedcharname[8];/*teachername*/unisgnedcharsex;/*teachersex,asfollows*//*0-FEMALE;1-MALE*/}TEACHER;typedefstructSTUDENT_STRU{unsignedcharname[8];/*student'sname*/unsignedcharage;/*student'sage*/unsignedcharsex;/*student'ssex,asfollows*//*0-FEMALE;1-MALE*/unsignedintteacher_ind;/*histeacherindex*/}STUDENT;不要設計面面俱到、非常靈活的數據結構說明:面面俱到、靈活的數據結構反而容易引起誤解和操作困難。不同結構間的關系不要過于復雜說明:若兩個結構間關系較復雜、密切,那么應合為一個結構。示例:如下兩個結構的構造不合理。typedefstructPERSON_ONE_STRU{unsignedcharname[8];unsignedcharaddr[40];unsignedcharsex;unsignedcharcity[15];}PERSON_ONE;typedefstructPERSON_TWO_STRU{unsignedcharname[8];unsignedcharage;unsignedchartel;}PERSON_TWO;由于兩個結構都是描述同一事物的,那么不如合成一個結構。typedefstructPERSON_STRU{unsignedcharname[8];unsignedcharage;unsignedcharsex;unsignedcharaddr[40];unsignedcharcity[15];unsignedchartel;}PERSON;結構中元素的個數應適中若結構中元素個數過多可考慮依據某種原則把元素組成不同的子結構,以減少原結構中元素的個數。說明:增加結構的可理解性、可操作性和可維護性。示例:假如認為如上的_PERSON結構元素過多,那么可如下對之劃分。typedefstructPERSON_BASE_INFO_STRU{unsignedcharname[8];unsignedcharage;unsignedcharsex;}PERSON_BASE_INFO;typedefstructPERSON_ADDRESS_STRU{unsignedcharaddr[40];unsignedcharcity[15];unsignedchartel;}PERSON_ADDRESS;typedefstructPERSON_STRU{PERSON_BASE_INFOperson_base;PERSON_ADDRESSperson_addr;}PERSON;結構中元素布局和排列仔細設計結構中元素的布局與排列順序,使結構容易理解、節(jié)省占用空間,并減少引起誤用現象。說明:合理排列結構中元素順序,可節(jié)省空間并增加可理解性。示例:如下結構中的位域排列,將占較大空間,可讀性也稍差。typedefstructEXAMPLE_STRU{unsignedintvalid:1;PERSONperson;unsignedintset_flg:1;}EXAMPLE;若改成如下形式,不僅可節(jié)省1字節(jié)空間,可讀性也變好了。typedefstructEXAMPLE_STRU{unsignedintvalid:1;unsignedintset_flg:1;PERSONperson;}EXAMPLE;結構中的保留項結構的設計要盡量考慮向前兼容和以后的版本升級,并為某些未來可能的應用保留余地(如預留一些空間等)。說明:軟件向前兼容的特性,是軟件產品是否成功的重要標志之一。如果要想使產品具有較好的前向兼容,那么在產品設計之初就應為以后版本升級保留一定余地,并且在產品升級時必須考慮前一版本的各種特性。留心具體語言及編譯器處理不同數據類型的原則及有關細節(jié)。說明:如在C語言中,static局部變量將在內存“數據區(qū)”中生成,而非static局部變量將在“堆?!敝猩伞_@些細節(jié)對程序質量的保證非常重要。編程時,要注意數據類型的強制轉換。說明:當進行數據類型強制轉換時,其數據的意義、轉換后的取值等都有可能發(fā)生變化,而這些細節(jié)若考慮不周,就很有可能留下隱患。對編譯系統(tǒng)默認的數據類型轉換,也要有充分的認識。示例:如下賦值,多數編譯器不產生告警,但值的含義還是稍有變化。charchr;unsignedshortintexam;chr=-1;exam=chr;//編譯器不產生告警,此時exam為0xFFFF。盡量減少沒有必要的數據類型默認轉換與強制轉換。合理地設計數據并使用自定義數據類型,避免數據間進行不必要的類型轉換。對自定義數據類型進行恰當命名,使它成為自描述性的,以提高代碼可讀性。注意其命名方式在同一產品中的統(tǒng)一。說明:使用自定義類型,可以彌補編程語言提供類型少、信息量不足的缺點,并能使程序清晰、簡潔。示例:可參考如下方式聲明自定義數據類型。下面的聲明可使數據類型的使用簡潔、明了。typedefunsignedcharBYTE;typedefunsignedshortWORD;typedefunsignedintDWORD;下面的聲明可使數據類型具有更豐富的含義。typedeffloatDISTANCE;typedeffloatSCORE;當聲明用于分布式環(huán)境或不同CPU間通信環(huán)境的數據結構時,必須考慮機器的字節(jié)順序、使用的位域及字節(jié)對齊等問題。說明:比如IntelCPU與68360CPU,在處理位域及整數時,其在內存存放的“順序”正好相反。示例:假如有如下短整數及結構。unsignedshortintexam;typedefstructEXAM_BIT_STRU{/*Intel68360*/unsignedintA1:1;/*bit07*/unsignedintA2:1;/*bit16*/unsignedintA3:1;/*bit25*/}EXAM_BIT;如下是IntelCPU生成短整數及位域的方式。內存:012...(從低到高,以字節(jié)為單位)examexam低字節(jié)exam高字節(jié)內存:0bit1bit2bit...(字節(jié)的各“位”)EXAM_BITA1A2A如下是68360CPU生成短整數及位域的方式。內存:012...(從低到高,以字節(jié)為單位)examexam高字節(jié)exam低字節(jié)內存:7bit6bit5bit...(字節(jié)的各“位”)EXAM_BITA1A2A說明:在對齊方式下,CPU的運行效率要快得多。示例:如下圖,當一個long型數(如圖中l(wèi)ong1)在內存中的位置正好與內存的字邊界對齊時,CPU存取這個數只需訪問一次內存,而當一個long型數(如圖中的long2)在內存中的位置跨越了字邊界時,CPU存取這個數就需要多次訪問內存,如i960cx訪問這樣的數需讀內存三次(一個BYTE、一個SHORT、一個BYTE,由CPU的微代碼執(zhí)行,對軟件透明),所有對齊方式下CPU的運行效率明顯快多了。 18162432 |long1|long1|long1|long1| ||||long2| |long2|long2|long2|| |函數、過程對所調用函數的錯誤返回碼要仔細、全面地處理。明確函數功能,精確(而不是近似)地實現函數設計。局部變量編寫可重入函數時,應注意局部變量的使用(如編寫C/C++語言的可重入函數時,應使用auto即缺省態(tài)局部變量或寄存器變量)。說明:編寫C/C++語言的可重入函數時,不應使用static局部變量,否則必須經過特殊處理,才能使函數具有可重入性。全局變量編寫可重入函數時,若使用全局變量,則應通過關中斷、信號量(即P、V操作)等手段對其加以保護。說明:若對所使用的全局變量不加以保護,則此函數就不具有可重入性,即當多個進程調用此函數時,很有可能使有關全局變量變?yōu)椴豢芍獱顟B(tài)。示例:假設Exam是int型全局變量,函數Squre_Exam返回Exam平方值。那么如下函數不具有可重入性。unsignedintexample(intpara){unsignedinttemp;Exam=para;//(**)temp=Square_Exam();returntemp;}此函數若被多個進程調用的話,其結果可能是未知的,因為當(**)語句剛執(zhí)行完后,另外一個使用本函數的進程可能正好被激活,那么當新激活的進程執(zhí)行到此函數時,將使Exam賦與另一個不同的para值,所以當控制重新回到“temp=Square_Exam()”后,計算出的temp很可能不是預想中的結果。此函數應如下改進。unsignedintexample(intpara){unsignedinttemp;[申請信號量操作]//若申請不到“信號量”,說明另外的進程正處于Exam=para;//給Exam賦值并計算其平方過程中(即正在使用此temp=Square_Exam();//信號),本進程必須等待其釋放信號后,才可繼[釋放信號量操作]//續(xù)執(zhí)行。若申請到信號,則可繼續(xù)執(zhí)行,但其//它進程必須等待本進程釋放信號量后,才能再使//用本信號。returntemp;}接口函數參數在同一項目組應明確規(guī)定對接口函數參數的合法性檢查應由函數的調用者負責還是由接口函數本身負責,缺省是由函數調用者負責。說明:對于模塊間接口函數的參數的合法性檢查這一問題,往往有兩個極端現象,即:要么是調用者和被調用者對參數均不作合法性檢查,結果就遺漏了合法性檢查這一必要的處理過程,造成問題隱患;要么就是調用者和被調用者均對參數進行合法性檢查,這種情況雖不會造成問題,但產生了冗余代碼,降低了效率。其他防止將函數的參數作為工作變量。說明:將函數的參數作為工作變量,有可能錯誤地改變參數內容,所以很危險。對必須改變的參數,最好先用局部變量代之,最后再將該局部變量的內容賦給該參數。示例:下函數的實現不太好。voidsum_data(unsignedintnum,int*data,int*sum){unsignedintcount;*sum=0;for(count=0;count<num;count++){*sum+=data[count];//sum成了工作變量,不太好。}}若改為如下,則更好些。voidsum_data(unsignedintnum,int*data,int*sum){unsignedintcount;intsum_temp;sum_temp=0;for(count=0;count<num;count++){sum_temp+=data[count];}*sum=sum_temp;}函數的規(guī)模盡量限制在200行以內。說明:不包括注釋和空格行。一個函數僅完成一件功能。為簡單功能編寫函數。說明:雖然為僅用一兩行就可完成的功能去編函數好象沒有必要,但用函數可使功能明確化,增加程序可讀性,亦可方便維護、測試。示例:如下語句的功能不很明顯。value=(a>b)?a:b;改為如下就很清晰了。intmax(inta,intb){return((a>b)?a:b);}value=max(a,b);或改為如下。#defineMAX(a,b)(((a)>(b))?(a):(b))value=MAX(a,b);不要設計多用途面面俱到的函數。說明:多功能集于一身的函數,很可能使函數的理解、測試、維護等變得困難。函數的功能應該是可以預測的,也就是只要輸入數據相同就應產生同樣的輸出。說明:帶有內部“存儲器”的函數的功能可能是不可預測的,因為它的輸出可能取決于內部存儲器(如某標記)的狀態(tài)。這樣的函數既不易于理解又不利于測試和維護。在C/C++語言中,函數的static局部變量是函數的內部存儲器,有可能使函數的功能不可預測,然而,當某函數的返回值為指針類型時,則必須是STATIC的局部變量的地址作為返回值,若為AUTO類,則返回為錯針。示例:如下函數,其返回值(即功能)是不可預測的。unsignedintinteger_sum(unsignedintbase){unsignedintindex;staticunsignedintsum=0;//注意,是static類型的。//若改為auto類型,則函數即變?yōu)榭深A測。for(index=1;index<=base;index++){sum+=index;}returnsum;}盡量不要編寫依賴于其他函數內部實現的函數。說明:此條為函數獨立性的基本要求。由于目前大部分高級語言都是結構化的,所以通過具體語言的語法要求與編譯器功能,基本就可以防止這種情況發(fā)生。但在匯編語言中,由于其靈活性,很可能使函數出現這種情況。示例:如下是在DOS下TASM的匯編程序例子。過程Print_Msg的實現依賴于Input_Msg的具體實現,這種程序是非結構化的,難以維護、修改。...//程序代碼procPrint_Msg//過程(函數)Print_Msg...//程序代碼jmpLABEL...//程序代碼endpprocInput_Msg//過程(函數)Input_Msg...//程序代碼LABEL:...//程序代碼endp避免設計多參數函數,不使用的參數從接口中去掉。說明:目的減少函數間接口的復雜度。非調度函數應減少或防止控制參數,盡量只使用數據參數。說明:本建議目的是防止函數間的控制耦合。調度函數是指根據輸入的消息類型或控制命令,來啟動相應的功能實體(即函數或過程),而本身并不完成具體功能??刂茀凳侵父淖兒瘮倒δ苄袨榈膮担春瘮狄鶕藚祦頉Q定具體怎樣工作。非調度函數的控制參數增加了函數間的控制耦合,很可能使函數間的耦合度增大,并使函數的功能不唯一。示例:如下函數構造不太合理。intadd_sub(inta,intb,unsignedcharadd_sub_flg){if(add_sub_flg==INTEGER_ADD){return(a+b);}else{return(a