




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、C編碼規(guī)范109條規(guī)則49條建議目 錄1.文件結(jié)構(gòu)(4條規(guī)則6條建議). 11.1 版權(quán)和版本的聲明. 11.2 頭文件的結(jié)構(gòu). 21.3 定義文件的結(jié)構(gòu). 31.4頭文件和定義文件使用(4條規(guī)則6條建議). 32.程序版式(34條規(guī)則2條建議). 42.1 空行(4條規(guī)則). 42.2 代碼行(5條規(guī)則1條建議). 42.3 代碼行內(nèi)的空格(6條規(guī)則1條建議). 52.4 對齊(4條規(guī)則). 62.5 長行拆分(2條規(guī)則). 72.6 修飾符的位置(1條規(guī)則). 82.7 注釋(12條規(guī)則). 83.標(biāo)識符命名(15條規(guī)則1條建議). 84.常量(7條規(guī)則). 104.1 const 與#d
2、efine 的比較(2條規(guī)則). 104.2 常量定義(5條規(guī)則). 105.變量(11條規(guī)則). 116.表達(dá)式和基本語句(17條規(guī)則3條建議). 116.1 運(yùn)算符的優(yōu)先級(1條規(guī)則). 116.2 復(fù)合表達(dá)式(4條規(guī)則). 126.3 if 語句布爾表達(dá)式(7條規(guī)則). 126.4 循環(huán)語句(1條規(guī)則3條建議). 156.5 switch 語句(2條規(guī)則). 166.6 goto 語句(1條規(guī)則). 167.函數(shù)設(shè)計(jì)(16條規(guī)則10條建議). 167.1注釋規(guī)則(1條規(guī)則). 167.2 函數(shù)的使用(1條規(guī)則). 167.3 參數(shù)的規(guī)則(4條規(guī)則2條建議). 177.4 返回值的規(guī)則(6
3、條規(guī)則). 177.5 函數(shù)內(nèi)部實(shí)現(xiàn)的規(guī)則(2條規(guī)則). 177.6 其它建議(6條建議). 187.7 使用斷言(2條規(guī)則2條建議). 188.內(nèi)存管理(5條規(guī)則). 188.1 內(nèi)存使用注意的問題(5條規(guī)則). 189.其他規(guī)范及建議(27條建議). 199.1 提高程序的效率(6條建議). 199.2 編譯問題(2條建議). 199.3 兼容性問題(8條建議). 199.4性能問題(4條建議). 199.5 其他一些有益的建議(7條建議). 201.文件結(jié)構(gòu)(4條規(guī)則6條建議)C程序文件通常分為兩類文件:一類文件用于保存程序的聲明(declaration),稱為頭文件。頭文件以“.h”為
4、后綴。另一類文件用于保存程序的實(shí)現(xiàn)(implementation),稱為定義(definition)文件。定義文件以“.c”為后綴。對于簡單的C語言程序,一般在把頭文件和程序定義文件放在一起,只有一個(gè).c定義文件即可。而對于復(fù)雜的程序,則多采用頭文件包含的形式并通過多個(gè)定義文件實(shí)現(xiàn)。 1.1 版權(quán)和版本的聲明 版權(quán)和版本的聲明一般應(yīng)該位于頭文件和定義文件的開頭(參見示例1-1),主要內(nèi)容包括:(1) 版權(quán)信息;(2) 文件名稱、文件標(biāo)識、摘要;(3) 當(dāng)前版本號、作者/修改者、修改日期、修改描述等;(4) 版本歷史信息、原作者、完成日期等。 示例1-1 版權(quán)和版本的聲明版本標(biāo)識:采用. 來命名
5、自己產(chǎn)品的編號。一般這樣約定,如果次版本號是偶數(shù)(如0、2、4等),代表正式版本,如果次版本號是奇數(shù)(如1、3、5等),代表開發(fā)過程中的測試版本。修訂號則相當(dāng)于Build號,用來標(biāo)識一些小的改動。1.2 頭文件的結(jié)構(gòu)頭文件由三部分內(nèi)容組成:(1) 文件開頭處的版權(quán)和版本聲明(參見示例1-1);(2) 預(yù)處理塊;(3) 聲明函數(shù)原型和聲明數(shù)據(jù)結(jié)構(gòu)或變量等。假設(shè)頭文件名稱為filename.h,頭文件的結(jié)構(gòu)參見示例1-2。/* Copyright (c) 2004,北大青鳥培訓(xùn)中心* All rights reserved.* 文件名稱:filename.h* 文件標(biāo)識:根據(jù)軟件工程設(shè)置* 摘要:
6、簡要描述本文件的作用和內(nèi)容等*/#include #include #include / 引用頭文件 struct studentstructint no; char name20; char sex; float score;void GetValue() void SetValue(int no) /后面同示例 1-1。示例1-2 C頭文件結(jié)構(gòu) 1.3 定義文件的結(jié)構(gòu)定義文件有三部分內(nèi)容:(1) 定義文件開頭處的版權(quán)和版本聲明(參見示例1-1);(2) 對一些頭文件的引用;(3) 程序的實(shí)現(xiàn)體(包括數(shù)據(jù)和代碼)。假設(shè)定義文件的名稱為filename.c,定義文件的結(jié)構(gòu)參見示例1-3 示例1
7、-3 C定義文件的結(jié)構(gòu)1.4頭文件和定義文件使用(4條規(guī)則6條建議)【規(guī)則1-2-1】在復(fù)雜的工程文件中,為了防止頭文件被重復(fù)引用,應(yīng)使用ifndef/define/endif 結(jié)構(gòu)產(chǎn)生預(yù)處理塊?!疽?guī)則1-2-2】用#include 格式來引用標(biāo)準(zhǔn)庫的頭文件(編譯器將從標(biāo)準(zhǔn)庫目錄開始搜索)。【規(guī)則1-2-3】用#include “filename.h” 格式來引用非標(biāo)準(zhǔn)庫的頭文件(編譯器將從用戶的工作目錄開始搜索)。【規(guī)則1-2-4】只引用必需的頭文件,不要為了防止忘記包含頭文件而在每個(gè)文件開始添加很多的頭文件。 【建議1-2-1】不要在頭文件中定義常量或變量,注意頭文件只是用來聲明?!窘ㄗh1
8、-2-2】不提倡使用全局變量,盡量不要在頭文件中出現(xiàn)像“extern int width;”這類聲明?!窘ㄗh1-2-3】將非系統(tǒng)的函數(shù)庫放在一個(gè)單獨(dú)的目錄下引用?!窘ㄗh1-2-4】頭文件應(yīng)按功能組織在一起,即對單獨(dú)子系統(tǒng)的聲明應(yīng)放在單獨(dú)的頭文件中。此外,當(dāng)代碼從一個(gè)平臺移植到另一個(gè)平臺時(shí)有可能發(fā)生更改的聲明應(yīng)位于單獨(dú)的頭文件中,并進(jìn)行相應(yīng)的注釋。【建議1-2-5】避免使用與函數(shù)庫中專用頭文件名相同的頭文件名。語句 #include math.h 如果在當(dāng)前目錄中找不到所期望文件的話,會包括標(biāo)準(zhǔn)庫 math 頭文件。【建議1-2-6】包含頭文件時(shí)一般不使用絕對路徑名。2.程序版式(35條規(guī)則2條
9、建議)2.1 空行(4條規(guī)則)空行起著分隔程序段落的作用,空行得體將使程序的布局更加清晰??招胁粫速M(fèi)內(nèi)存,所以不要舍不得用空行。【規(guī)則2-1-1】在函數(shù)內(nèi)部局部變量定義結(jié)束之后處理語句之前要加空行?!疽?guī)則2-1-2】在每個(gè)函數(shù)定義結(jié)束之后都要加空行。參見示例2-1(a)。【規(guī)則2-1-3】函數(shù)返回語句和其他語句之間使用空行分開?!疽?guī)則2-1-4】在一個(gè)函數(shù)體內(nèi),邏輯上密切相關(guān)的語句之間不加空行,其它地方應(yīng)加空行分隔。參見示例2-1(b)。 / 空行void Function1( ) / 空行void Function2( ) / 空行void Function3( ) 示例2-1(a) 函數(shù)
10、之間的空行 示例2-1(b) 函數(shù)內(nèi)部的空行 2.2 代碼行(5條規(guī)則1條建議)【規(guī)則2-2-1】一行代碼只做一件事情,如只定義一個(gè)變量,或只寫一條語句。這樣的代碼容易閱讀,并且方便寫注釋?!疽?guī)則2-2-2】if、for、while、do 等語句自占一行,執(zhí)行語句不得緊跟其后。不論執(zhí)行語句有多少都要加表明是一個(gè)語句塊?!疽?guī)則2-2-3】一對花括號要單獨(dú)各占一行。但是在do-while、struct和union及其后有;的除外,要同在一行。例如: 【規(guī)則2-2-4】switch語句中的每個(gè)case語句各占一行,當(dāng)某個(gè)case語句不需要break語句最好加注釋聲明?!疽?guī)則2-2-5】并列的語句行應(yīng)
11、該按照字母順序排序,如變量定義和switch中的case語句等。 【建議2-2-1】盡可能在定義變量的同時(shí)初始化該變量(就近原則),如果變量的引用處和其定義處相隔較遠(yuǎn),變量的初始化很容易被忘記。如果引用了未被初始化的變量,可能會導(dǎo)致程序錯(cuò)誤。本建議可以減少隱患。例如:int width=20; /* 定義并初紿化width*/int height=20; /* 定義并初紿化height*/int depth=20; /* 定義并初紿化depth*/ 風(fēng)格良好的代碼行風(fēng)格不良的代碼行int width; /* 寬度*/int height; /* 高度*/int depth; /* 深度*/in
12、t width, height, depth; /* 寬度高度深度*/ x=a+b;y=c+d;z=e+f;x=a+b;y=c+d;z=e+f; if( width height )dosomething();if( width =”、“=”、“+”、“*”、“%”、“&”、“|”、“”這類操作符前后不加空格。 例如:big.bar,pFile-bar,bigbar【建議2-3-1】對于表達(dá)式較長的for語句和if語句,為了緊湊起見可以適當(dāng)?shù)厝サ粢恍┛崭? 例如:for( i=0; i10; i+ )和if( (a=b) & (c= 2000 )if( (a=b) & (c=2000)if(a
13、=b&c=d)for( i=0; i10; i+ )for(i=0;i10;i+)for (i = 0; i 10; i +)x = a b ? a : b;x=aFunction();array 5 = 0;a.Function();b - Function();2.4 對齊(4條規(guī)則)【規(guī)則2-4-1】程序的分界符和應(yīng)獨(dú)占一行并且位于同一列,同時(shí)與引用它們的語句左對齊。【規(guī)則2-4-2】水平縮進(jìn)每次使用四個(gè)空格即可(定義一個(gè)tab鍵為四個(gè)空格。有的要求縮進(jìn)兩個(gè)空格)?!疽?guī)則2-4-3】同屬于一個(gè)語句塊的代碼對齊?!疽?guī)則2-4-4】 之內(nèi)的代碼塊在右邊一個(gè)tab鍵處左對齊。風(fēng)格良好的對齊風(fēng)格
14、不良的對齊void Function(int x) program codevoid Function(int x)program codeif( condition ) program codeelse program codeif(condition)program codeelse program codefor( initialization; condition; update ) program codefor(initialization; condition; update)program codewhile( condition ) program codewhile(con
15、dition)program code 如果出現(xiàn)嵌套的,則使用縮進(jìn)對齊,如: 2.5 長行拆分(2條規(guī)則)【規(guī)則2-5-1】代碼行最大長度宜控制在70至80個(gè)字符以內(nèi)。代碼行不宜過長,否則不便于閱讀,也不便于打印?!疽?guī)則2-5-2】長表達(dá)式要在低優(yōu)先級操作符處拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要進(jìn)行適當(dāng)?shù)目s進(jìn),使排版整齊,語句可讀。if( (very_longer_variable1 = very_longer_variable12 )& (very_longer_variable3 = very_longer_variable14)& (very_longer_v
16、ariable5 = very_longer_variable16)dosomething();virtual CMatrix CMultiplyMatrix (CMatrix leftMatrix,CMatrix rightMatrix);for( very_long_initialization;very_long_condition;very_long_update)dosomething();示例2-5 長行的拆分 2.6 修飾符的位置(1條規(guī)則)【規(guī)則2-6-1】將修飾符 * 和 緊靠變量名,以免引起誤解。例如:char *name;int *x, y; /* 此處y 不會被誤解為指
17、針*/2.7 注釋(12條規(guī)則)C 語言的注釋符為“/* */”和“/”。注釋通常用于:(1)版本、版權(quán)聲明;(2)函數(shù)接口說明,包括參數(shù)類型和意義、函數(shù)類型和意義等;(3)重要的數(shù)據(jù)類型聲明、變量、算法、處理、段落等提示?!?”為行注釋。【規(guī)則2-7-1】注釋是對代碼作用的“提示”,而不是文檔。注釋的頻度要合適,一般要求占程序總行數(shù)的1/51/4。【規(guī)則2-7-2】邊寫代碼邊注釋,修改代碼同時(shí)修改相應(yīng)的注釋,以保證注釋與代碼的一致性。不再有用的注釋要?jiǎng)h除?!疽?guī)則2-7-3】注釋應(yīng)準(zhǔn)確、易懂,防止注釋有二義性。錯(cuò)誤的注釋不但無益反而有害?!疽?guī)則2-7-4】盡量避免在注釋中使用縮寫,特別是不常用
18、的縮寫。根據(jù)維護(hù)程序的對象確定使用中文還是使用英文。【規(guī)則2-7-5】注釋的位置應(yīng)與被描述代碼相鄰,可以放在代碼的上方或右方,一般不宜放在下方。【規(guī)則2-7-6】當(dāng)代碼比較長,特別是有多重嵌套時(shí),應(yīng)當(dāng)在一些段落的結(jié)束處加注釋,便于閱讀?!疽?guī)則2-7-7】盡量不要在語句指令中添加注釋?!疽?guī)則2-7-8】注釋不具備約束使用者行為的能力。【規(guī)則2-7-9】給一行代碼添加注釋最好使用“/”,比較清楚?!疽?guī)則2-7-10】不要使用/*/注釋掉大量代碼,而要使用#if0條件編譯語句例如:【規(guī)則2-7-11】行末注釋最好對齊?!疽?guī)則2-7-12】應(yīng)對包含的頭文件進(jìn)行行末注釋。 3.標(biāo)識符命名(15條規(guī)則1條
19、建議)共性規(guī)則是被大多數(shù)程序員采納的,我們應(yīng)當(dāng)在遵循這些共性規(guī)則。命名兩個(gè)基本原則:1.含義清晰,不易混淆;2.不與其它模塊、函數(shù)的命名空間相沖突?!疽?guī)則3-1-1】標(biāo)識符要清楚、準(zhǔn)確、簡單而且盡量可發(fā)音的英文名字。 例如:int returnStatus; 不要把currentValue 寫成nowValue 。【規(guī)則3-1-2】標(biāo)識符的長度應(yīng)當(dāng)符合“min-length & max-information”(最短并包含信息最多)原則。單字符的名字也是有用的,常見的如i、j、k、m、n、x、y、z 等,它們通??捎米骱瘮?shù)內(nèi)的局部變量。【規(guī)則3-1-3】命名規(guī)則盡量與所采用的操作系統(tǒng)或開發(fā)工具
20、的風(fēng)格保持一致。 例如Windows應(yīng)用程序的標(biāo)識符通常采用“大小寫”混排的方式,如printStudent;而Unix 應(yīng)用程序的標(biāo)識符通常采用“小寫加下劃線”的方式,如print_student。別把這兩類風(fēng) 格混在一起用。【規(guī)則3-1-4】盡量選擇通用詞匯并保持整個(gè)軟件風(fēng)格一致。 例如:使用get、read、fetch 、retrieve都能表達(dá)“取出”的意思,一旦軟件采用哪一 個(gè)則應(yīng)貫穿始終?!疽?guī)則3-1-5】程序中不要出現(xiàn)僅靠大小寫區(qū)分的相似的標(biāo)識符。 例如:int x, X; /* 變量x 與X 容易混淆*/ void foo(int y); /* 函數(shù)foo 與FOO 容易混淆*
21、/void FOO(float y);【規(guī)則3-1-6】程序中不要出現(xiàn)標(biāo)識符完全相同的局部變量和全局變量,盡管可能兩者的作用域不同而不會發(fā)生語法錯(cuò)誤,但會使人誤解?!疽?guī)則3-1-7】變量的名字應(yīng)當(dāng)使用“名詞”或者“形容詞名詞”。 例如: float value; float newValue;【規(guī)則3-1-8】用正確的反義詞組命名具有互斥意義的變量或相反動作的函數(shù)等。 例如: int MinValue; int MaxValue; int MinValue(void); int MaxValue(void);【規(guī)則3-1-9】變量和參數(shù)首字母小寫,其后每個(gè)英文單詞的第一個(gè)字母大寫,其它小寫。
22、例如:int recWidth;【規(guī)則3-1-10】標(biāo)識布爾型的變量或函數(shù)名稱一般使用is作為前綴。 例如:void isFull();【規(guī)則3-1-11】常量全用大寫字母,用下劃線分割單詞。 const int MAX_LENGTH = 100;【規(guī)則3-1-12】靜態(tài)變量加前綴s_(表示static)。 static int s_initValue; /* 靜態(tài)變量*/【規(guī)則3-1-13】如果需要定義全局變量,則變量加前綴g_(表示global)。 例如:int g_howStudent; /* 全局變量*/【規(guī)則3-1-14】函數(shù)名用大寫字母開頭的單詞組合而成。由多個(gè)單詞組成的標(biāo)識符每個(gè)
23、單詞首字母大寫。其它小寫。 例如:InputStudInfo(); /全局函數(shù)【規(guī)則3-1-15】一般錯(cuò)誤包裹函數(shù)名全部大寫。 例如: 可以定義成下面的包裹函數(shù)以后調(diào)用的話,則可以使用下面的簡潔方式:FILE *pFile=FOPEN(readme.txt,rw+); 【建議3-1-1】盡量避免名字中出現(xiàn)數(shù)字編號,如value1、value2 等,除非邏輯上的確需要編號。 4.常量(7條規(guī)則)常量是一種標(biāo)識符,它的值在運(yùn)行期間恒定不變。C 語言用#define 來定義常量。除了#define之外還可以用const 來定義常量。4.1 const 與#define 的比較(2條規(guī)則)C 語言可以
24、用const 來定義常量,也可以用#define 來定義常量。但是前者比后者有更多的優(yōu)點(diǎn):(1) const 常量有數(shù)據(jù)類型,而宏常量沒有數(shù)據(jù)類型。編譯器可以對前者進(jìn)行類型安全檢查。而對后者只進(jìn)行字符替換,沒有類型安全檢查,并且在字符替換過程中可能會產(chǎn)生意料不到的錯(cuò)誤。(2) 有些集成化的調(diào)試工具可以對const 常量進(jìn)行調(diào)試,但是不能對宏常量進(jìn)行調(diào)試。【規(guī)則4-1-1】盡量使用含義直觀的常量來表示那些將在程序中多次出現(xiàn)的數(shù)字或字符串。 例如: #define MAX 100 / C 語言的宏常量 const float PI = 3.14159; / C 語言的const 常量【規(guī)則4-1-
25、2】盡量使用const定義常量替代宏定義常量。4.2 常量定義(5條規(guī)則)【規(guī)則4-2-1】需要對外公開的常量放在頭文件中,不需要對外公開的常量放在定義文件的頭部。為便于管理,可以把不同模塊的常量集中存放在一個(gè)公共的頭文件中?!疽?guī)則4-2-2】如果某一常量與其它常量密切相關(guān),則應(yīng)在定義中包含這種關(guān)系,而不應(yīng)給出一些孤立的值。 例如: const float RADIUS = 100; const float DIAMETER = RADIUS * 2;【規(guī)則4-2-3】enum中的枚舉常量應(yīng)以大寫字母開頭或全部大寫。【規(guī)則4-2-4】如果宏值多于一項(xiàng),一定使用括號。 例如:#define ER
26、ROR_DATA_LENGTH 10+1 應(yīng)該這樣定義: #define ERROR_DATA_LENGTH (10+1) 這樣使用malloc(5*ERROR_DATA_LENGTH)時(shí),得到是5*(10+1)=55; 而上面的定義則得到5*10+1=51?!疽?guī)則4-2-5】函數(shù)宏的每個(gè)參數(shù)都要括起來。 例如:#define WEEKS_TO_DAYS(w) (w*7) 應(yīng)該寫成:#define WEEKS_TO_DAYS(w) (w)*7) 這樣在翻譯totalDaysWEEKS_TO_DAYS(1+2)時(shí),才能夠正確地翻譯成:(1+2)*7;否則將錯(cuò)誤地翻譯成1+2*7。5.變量(11條
27、規(guī)則)【規(guī)則5-1-1】局部變量在引用之前要進(jìn)行出初始化或要有明確的值?!疽?guī)則5-1-2】如果指針變量知道被初始化為什么地址,則初始化為該地址,否則初始化為NULL?!疽?guī)則5-1-3】所有的外部變量聲明前都應(yīng)加上extern關(guān)鍵字?!疽?guī)則5-1-4】盡量不要使用一個(gè)bit位控制程序流程或標(biāo)識特定狀態(tài)。最好使用多位或枚舉類型標(biāo)識狀態(tài)?!疽?guī)則5-1-5】如果定義數(shù)組時(shí)全部初始化,則不用給出數(shù)組長度。 例如:int array1,2,3,4,5;在需要使用數(shù)組長度時(shí),用sizeof(array)/sizeof(array0)計(jì)算得出?!疽?guī)則5-1-6】不同文件的全局變量沒有固定的初始化順序,注意使用
28、#include包括的文件都算作同一文件。【規(guī)則5-1-7】盡量避免強(qiáng)制類型轉(zhuǎn)換;如果不得不使用,則盡量使用顯式方式。【規(guī)則5-1-8】不要強(qiáng)制指針指向尺寸不同的目標(biāo)。例如:int Function(const char* pChar ) int *pInt=(const int*)pChar;/*危險(xiǎn)操作*/ return(*pInt);【規(guī)則5-1-9】盡量少使用無符號類型,其在混合表達(dá)式中可能隱式轉(zhuǎn)換造成錯(cuò)誤。【規(guī)則5-1-10】盡量少的使用浮點(diǎn)類型,因?yàn)楦↑c(diǎn)數(shù)據(jù)標(biāo)識不精確,而且運(yùn)算速度慢?!疽?guī)則5-1-11】盡量少用union類型,因?yàn)槌蓡T共用內(nèi)存空間,處理不當(dāng)容易出錯(cuò)。 6.表達(dá)式和
29、基本語句(17條規(guī)則3條建議)6.1 運(yùn)算符的優(yōu)先級(1條規(guī)則)【規(guī)則6-1-1】避免使用默認(rèn)的優(yōu)先級。如果代碼行中的運(yùn)算符比較多,為了防止產(chǎn)生歧義并提高可讀性,應(yīng)當(dāng)用括號明確表達(dá)式的計(jì)算順序。 例如:value = (high = b & cd & c+f=g+h ; / 復(fù)合表達(dá)式過于復(fù)雜【規(guī)則6-2-2】不要使用多用途的復(fù)合表達(dá)式。 例如:d=(a=b+c)+r ; /該表達(dá)式既求a 值又求d 值。 應(yīng)該拆分為兩個(gè)獨(dú)立的語句: a=b+c; d=a+r;【規(guī)則6-2-3】不要把程序中的復(fù)合表達(dá)式與“真正的數(shù)學(xué)表達(dá)式”混淆。 例如: if( abc ) /abc 是數(shù)學(xué)表達(dá)式而不是復(fù)合表達(dá)
30、式并不表示 if( (ab) & (bc) )而是成了令人費(fèi)解的 if( (ab)=”或“=-EPSINON ) & ( x=EPSINON) ) 其中EPSINON 是允許的誤差(即精度)?!疽?guī)則6-3-7】應(yīng)當(dāng)將指針變量用“=”或“!=”與NULL 比較。指針變量的零值是“空”(記為NULL)。盡管NULL 的值與0 相同,但是兩者意義不同。假設(shè)指針變量的名字為p,它與零值比較的標(biāo)準(zhǔn)if 語句如下:if( p= NULL ) / p 與NULL 顯式比較,強(qiáng)調(diào)p 是指針變量if( p!= NULL )不要寫成if( p=0 ) / 容易讓人誤解p 是整型變量if( p!=0 )或者if(
31、p ) / 容易讓人誤解p 是布爾變量if( !p ) 6.4 循環(huán)語句(1條規(guī)則3條建議)C語言的循環(huán)語句中,for 語句的使用頻率最高,while 語句其次,do 語句很少用。本節(jié)重點(diǎn)論述循環(huán)體的效率。提高循環(huán)體效率的基本辦法是降低循環(huán)體的復(fù)雜性?!疽?guī)則6-4-1】不可在循環(huán)體內(nèi)修改循環(huán)變量,以防止循環(huán)失去控制。 【建議6-4-1】在多重循環(huán)中,如果有可能,應(yīng)當(dāng)將最長的循環(huán)放在最內(nèi)層,最短的循環(huán)放在最外層,以減少CPU 跨切循環(huán)層的次數(shù)。如下表的對比: 低效率:長循環(huán)在最外層高效率:長循環(huán)在最內(nèi)層for ( row=0; row100; row+ )for ( col=0; col5; c
32、ol+ ) sum = sum + arowcol;for ( col=0; col5; col+ )for ( row=0; row100; row+ )sum = sum + arowcol; 【建議6-4-2】如果循環(huán)體內(nèi)存在邏輯判斷,并且循環(huán)次數(shù)很大,宜將邏輯判斷移到循環(huán)體的外面。下面示例a的程序比示例b程序多執(zhí)行了N-1 次邏輯判斷。并且由于前者總要進(jìn)行邏輯判斷,打斷了循環(huán)“流水線”作業(yè),使得編譯器不能對循環(huán)進(jìn)行優(yōu)化處理,降低了效率。如果N非常大,最好采用示例b的寫法,可以提高效率。如果N非常小,兩者效率差別并不明顯,采用示例a的寫法比較好,因?yàn)槌绦蚋雍啙崱H缦卤淼膶Ρ龋?a、效率
33、低但程序簡潔b、效率高但程序不簡潔for( i=0; iN; i+ )if ( condition ) DoSomething();else DoOtherthing(); if( condition )for( i=0; iN; i+ ) DoSomething();else for(i=0; iN; i+) DoOtherthing(); 【建議6-4-3】建議for 語句的循環(huán)控制變量的取值采用“半開半閉區(qū)間”寫法。示例a中的x 值屬于半開半閉區(qū)間“0 = x N”,起點(diǎn)到終點(diǎn)的間隔為N,循環(huán)次數(shù)為N。示例b中的x 值屬于閉區(qū)間“0 = x = N-1”,起點(diǎn)到終點(diǎn)的間隔為N-1,循環(huán)次
34、數(shù)為N。相比之下,示例a的寫法更加直觀,盡管兩者的功能是相同的。 a、循環(huán)變量屬于半開半閉區(qū)間b、循環(huán)變量屬于閉區(qū)間for( x=0; xN; x+ ).for( x=0; x=N-1; x+ ). 6.5 switch 語句(2條規(guī)則)【規(guī)則6-6-1】每個(gè)case 語句的結(jié)尾不要忘了加break語句,否則將導(dǎo)致多個(gè)分支重疊(除非有意使多個(gè)分支重疊)?!疽?guī)則6-6-2】不要忘記最后的default 分支。即使程序真的不需要default 處理,也應(yīng)該保留語句default : break;6.6 goto 語句(1條規(guī)則)【規(guī)則6-7-1】慎用goto 語句。雖然在某些情況使用方便,但是會造
35、成程序可讀性下降。 7.函數(shù)設(shè)計(jì)(17條規(guī)則10條建議)7.1注釋規(guī)則(1條規(guī)則)【規(guī)則7-1-1】一般在函數(shù)頭添加函數(shù)功能、參數(shù)說明、返回值等注釋信息。可以選擇在函數(shù)末尾添加該函數(shù)在單元測試中曾經(jīng)出現(xiàn)的問題。一個(gè)函數(shù)的注釋信息如下例:7.2 函數(shù)的使用(1條規(guī)則)【規(guī)則7-2-1】函數(shù)的扇入數(shù)目盡量多,扇出數(shù)目不宜太多,一般不超過10,以保證程序的高內(nèi)聚、 低藕和。7.3 參數(shù)的規(guī)則(4條規(guī)則2條建議)【規(guī)則7-3-1】參數(shù)的書寫要完整,不要貪圖省事只寫參數(shù)的類型而省略參數(shù)的名字。如果函數(shù)沒有參數(shù),則用void 填充。(使用函數(shù)原型)。例如: void SetValue(int width,
36、 int height); / 良好的風(fēng)格void SetValue(int, int); / 不良的風(fēng)格float GetValue(void); / 良好的風(fēng)格float GetValue(); / 不良的風(fēng)格【規(guī)則7-3-2】參數(shù)命名要恰當(dāng),順序要符合習(xí)慣用法。例如:編寫字符串拷貝函數(shù)StringCopy,它有兩個(gè)參數(shù)。如果把參數(shù)名字起為str1和str2,例如: void StringCopy(char *str1, char *str2);很難搞清楚究竟是把str1 拷貝到str2 中,還是相反??梢园褏?shù)名字起得更有意義,例如strSource 和strDestination。這樣
37、從名字上就可以看出應(yīng)該把strSource 拷貝到strDestination中。另外,參數(shù)的順序要遵循庫函數(shù)的風(fēng)格。一般地,應(yīng)將目的參數(shù)放在前面,源參數(shù)放在后面?!疽?guī)則7-3-3】如果參數(shù)是指針,且僅作輸入用,則應(yīng)在類型前加const,以防止該指針在函數(shù)體內(nèi)被意 外修改。例如:void StringCopy(char *strDestination,const char *strSource);【規(guī)則7-3-4】對于基本數(shù)據(jù)類型參數(shù)應(yīng)該傳遞值(除非函數(shù)要修改傳入的參數(shù)),這樣安全、簡單。對于復(fù)合數(shù)據(jù)類型應(yīng)傳遞指針(地址),以提高效率。 【建議7-3-1】避免函數(shù)有太多的參數(shù),參數(shù)個(gè)數(shù)盡量控制
38、在5個(gè)以內(nèi)。如果參數(shù)太多,在使用時(shí)容易將參數(shù)類型或順序搞錯(cuò)。【建議7-3-2】盡量不要使用類型和數(shù)目不確定的參數(shù)。 7.4 返回值的規(guī)則(6條規(guī)則)【規(guī)則7-4-1】不要省略返回值的類型。如果函數(shù)沒有返回值,那么應(yīng)聲明為void 類型?!疽?guī)則7-4-2】函數(shù)名字與返回值類型在語義上不可沖突。【規(guī)則7-4-3】函數(shù)返回正常值和錯(cuò)誤標(biāo)志要有明確的說明。【規(guī)則7-4-4】給以“指針傳遞”方式的函數(shù)返回值加const修飾,那么函數(shù)返回值(即指針)的內(nèi)容不能被修改,該返回值只能被賦給加const修飾的同類型指針。函數(shù)返回值采用“值傳遞方式”,由于函數(shù)會把返回值復(fù)制到外部臨時(shí)的存儲單元中,加const修飾
39、沒有任何價(jià)值。【規(guī)則7-4-5】返回指針類型的函數(shù)應(yīng)該使用NULL表示失敗?!疽?guī)則7-4-6】當(dāng)函數(shù)返回指針時(shí),應(yīng)用注釋描述指針的有效期。7.5 函數(shù)內(nèi)部實(shí)現(xiàn)的規(guī)則(2條規(guī)則)不同功能的函數(shù)其內(nèi)部實(shí)現(xiàn)各不相同,看起來似乎無法就“內(nèi)部實(shí)現(xiàn)”達(dá)成一致的觀點(diǎn)。但根據(jù)經(jīng)驗(yàn),我們可以在函數(shù)體的“入口處”和“出口處”從嚴(yán)把關(guān),從而提高函數(shù)的質(zhì)量?!疽?guī)則7-5-1】在函數(shù)體的“入口處”,對參數(shù)的有效性進(jìn)行檢查?!疽?guī)則7-5-2】盡量保持函數(shù)只有一個(gè)出口,在函數(shù)體的“出口處”,對return 語句的正確性和效率進(jìn) 行檢查。注意事項(xiàng)如下:(1)return 語句不可返回指向“棧內(nèi)存”的“指針”,因?yàn)樵搩?nèi)存在函數(shù)
40、體結(jié)束時(shí)被自動銷毀。例如: char * Func(void) char str = “hello student”; / str 的內(nèi)存位于棧上 return str; / 將導(dǎo)致錯(cuò)誤 (2)要搞清楚返回的究竟是“值”還是“指針”。 7.6 其它建議(6條建議)【建議7-6-1】函數(shù)的功能要單一,不要設(shè)計(jì)功能過于復(fù)雜的函數(shù)?!窘ㄗh7-6-2】經(jīng)常使用的重復(fù)代碼用函數(shù)來代替?!窘ㄗh7-6-3】函數(shù)體的規(guī)模要小,盡量控制在50 行代碼之內(nèi)。【建議7-6-4】盡量避免函數(shù)帶有“記憶”功能。相同的輸入應(yīng)當(dāng)產(chǎn)生相同的輸出。函數(shù)的static 局部變量是函數(shù)的“記憶”存儲器。建議盡量少用static 局
41、部變量,除非必需。【建議7-6-5】不僅要檢查輸入?yún)?shù)的有效性,還要檢查通過其它途徑進(jìn)入函數(shù)體內(nèi)的變量的有效性。 例如全局變量、文件句柄等?!窘ㄗh7-6-6】用于出錯(cuò)處理的返回值一定要清楚,讓使用者不容易忽視或誤解錯(cuò)誤情況。 7.7 使用斷言(2條規(guī)則2條建議)程序一般分為Debug 版本和Release 版本,Debug 版本用于內(nèi)部調(diào)試,Release 版本發(fā)行給用戶使用。斷言assert 是僅在Debug 中版本起作用的宏,它用于檢查“不應(yīng)該”發(fā)生的情況。在程序運(yùn)行過程中,如果assert 的參數(shù)為假,那么程序就會中止(一般還會出現(xiàn)提示對話,說明在什么地方引發(fā)了assert)。 asse
42、rt 不是一個(gè)倉促拼湊起來的宏。為了不在程序的Debug 版本和Release 版本引起差別,assert 不應(yīng)該產(chǎn)生任何副作用。所以assert 不是函數(shù),而是宏。程序員可以把a(bǔ)ssert 看成一個(gè)在任何系統(tǒng)狀態(tài)下都可以安全使用的無害測試手段。如果程序在assert處終止了,并不是說明含有該assert 的函數(shù)有錯(cuò)誤,而是調(diào)用者出了差錯(cuò),assert 可以幫助我們找到發(fā)生錯(cuò)誤的原因?!疽?guī)則7-7-1】使用斷言捕捉不應(yīng)該發(fā)生的非法情況。不要混淆非法情況與錯(cuò)誤情況之間的區(qū)別,后者是必然存在的并且是一定要作出處理的。【規(guī)則7-7-2】在函數(shù)的入口處,使用斷言檢查參數(shù)的有效性(合法性)。 【建議7-
43、7-1】在編寫函數(shù)時(shí),要進(jìn)行反復(fù)的考查,并且自問:“我打算做哪些假定?”一旦確定了的假定,就要使用斷言對假定進(jìn)行檢查?!窘ㄗh7-7-2】一般教科書都鼓勵(lì)程序員們進(jìn)行防錯(cuò)設(shè)計(jì),但要記住這種編程風(fēng)格可能會隱瞞錯(cuò)誤。當(dāng)進(jìn)行防錯(cuò)設(shè)計(jì)時(shí),如果“不可能發(fā)生”的事情的確發(fā)生了,則要使用斷言進(jìn)行報(bào)警。 8.內(nèi)存管理(5條規(guī)則)8.1 內(nèi)存使用注意的問題(5條規(guī)則)內(nèi)存分配方式有三種:(1) 從靜態(tài)存儲區(qū)域分配。內(nèi)存在程序編譯的時(shí)候就已經(jīng)分配好,這塊內(nèi)存在程序的整個(gè)運(yùn)行期間都存在。例如全局變量,static 變量。(2) 在棧上分配。在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲單元都在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí)這些存儲單元自動被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但是分配的內(nèi)存容量有限。(3) 從堆上分配,亦稱動態(tài)內(nèi)存分配。程序在運(yùn)行時(shí)用malloc或calloc申請任意大小的內(nèi)存,程序員自己負(fù)責(zé)在何時(shí)用free釋放內(nèi)存。動態(tài)內(nèi)存的生存期由程序員決定,使用非常靈活,但問題也最多。 【規(guī)則8-1-1】用malloc或calloc 申請內(nèi)存之后,應(yīng)該立即檢查指針值是
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 獸醫(yī)急救藥品使用試題及答案
- 氣象災(zāi)害的應(yīng)對與預(yù)防策略試題及答案
- 投資咨詢工程師投資策略試題及答案
- 如何做點(diǎn)名課件
- 創(chuàng)業(yè)低成本項(xiàng)目案例分享
- 勞動教育的意義與實(shí)施
- 人力資源管理師考試的模擬試題及答案
- 醫(yī)院急診部的工作效率提升計(jì)劃
- 應(yīng)對工作中突發(fā)事件的預(yù)案計(jì)劃
- 提升班級藝術(shù)活動參與度的策略計(jì)劃
- 企業(yè)廉潔風(fēng)險(xiǎn)防控課件教學(xué)
- 中醫(yī)護(hù)理三基練習(xí)題庫+答案
- 火龍罐綜合灸療法
- 形勢與政策(吉林大學(xué))智慧樹知到答案章節(jié)測試2023年
- 用戶中心積分成長值體系需求文檔
- 2021商超全年52周企劃MD營銷銷售計(jì)劃培訓(xùn)課件-96P
- 勞務(wù)派遣用工管理辦法
- 初中數(shù)學(xué)人教七年級下冊第七章 平面直角坐標(biāo)系 平面直角坐標(biāo)系中圖形面積的求法PPT
- 頰癌病人的護(hù)理查房
- 特種設(shè)備使用登記表(范本)
- YSJ 007-1990 有色金屬選礦廠 試驗(yàn)室、化驗(yàn)室及技術(shù)檢查站工藝設(shè)計(jì)標(biāo)準(zhǔn)(試行)(附條文說明)
評論
0/150
提交評論