版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、C語(yǔ)言寫規(guī)范指南第 1 章文件結(jié)構(gòu)每個(gè)C程序通常分為兩個(gè)文件。一個(gè)文件用于保存程序的聲明( 件。另一個(gè)文件用于保存程序的實(shí)現(xiàn)( implementation ),C程序的頭文件以“ .h”為后綴,C程序的定義文件以“declaration ),稱為頭文 稱為定義( definition )文件。.c”為后綴。版權(quán)和版本的聲明版權(quán)和版本的聲明位于頭文件和定義文件的開頭(參見示例 版權(quán)信息。文件名稱,標(biāo)識(shí)符,摘要。 當(dāng)前版本號(hào),作者 / 修改者,完成日期。 版本歷史信息。1-1),主要內(nèi)容有:1)2)3)4) /* *Copyright(c)2001, 吉林大學(xué)物理學(xué)院無線電*Allrightsr
2、eserved.* 文件名稱:* 文件標(biāo)識(shí):* 摘要: 簡(jiǎn)要描述本文件的內(nèi)容* 當(dāng)前版本:*作者: 輸入作者(或修改者)名字2007年7月20日*完成日期:*取代版本:*原作者*完成日期:輸入原作者(或修改者)名字2007年5月10日*/示例 1-1版權(quán)和版本的聲明1-1 )。1-2?!疽?guī)則1-2-1】【規(guī)則1-2-2】 索)?!疽?guī)則1-2-3】 始搜索)。【規(guī)則1-2-4】#ifndef/#define/#endif結(jié)構(gòu)產(chǎn)生預(yù)處理塊。為了防止頭文件被重復(fù)引用,應(yīng)當(dāng)用<>格式來引用標(biāo)準(zhǔn)庫(kù)的頭文件(編譯器將從標(biāo)準(zhǔn)庫(kù)目錄開始搜用 #include用 #include“格式來引用非標(biāo)準(zhǔn)庫(kù)
3、的頭文件(編譯器將從用戶的工作目錄開#include后面使用TAB鍵控制排版。頭文件的結(jié)構(gòu)頭文件由三部分內(nèi)容組成:(1) 頭文件開頭處的版權(quán)和版本聲明(參見示例(2) 預(yù)處理塊。(3) 函數(shù)和類結(jié)構(gòu)聲明等。假設(shè)頭文件名稱為,頭文件的結(jié)構(gòu)參見示例頭文件中只存放“聲明”而不存放“定義” 全局變量在頭文件中聲明,在.c文件中定義“->”這類操作符前后不加空格。【建議2-3-1】對(duì)于表達(dá)式比較長(zhǎng)的for語(yǔ)句和if語(yǔ)句,為了緊湊起見可以適當(dāng)?shù)厝サ粢恍┛?格,女0 for(i=0;i<10;i+)和 if(a<=b)&&(c<=d)【規(guī)則1-2-5】【規(guī)則1-2-6
4、】.h extern in tvalue; 聲明。.c in tvalue=0x10; 定義?!疽?guī)則1-2-7】局部變量在.c中定義(static) unsigned in tvalue;定義。void Fun c1(i nt x,i nt y,i nt z);Function。; b-> Function。;從左至右!+-(類型)sizeof+ - * &從右至左* / %從左至右+ -從左至右<< >>從左至右< <= > >=從左至右= !=從左至右&從左至右A從左至右|從左至右&&從左至右II從右至左
5、:從右至左= += -= *= /= %= &= A=|= <<= >>=從左至右表4-1運(yùn)算符的優(yōu)先級(jí)與結(jié)合律【規(guī)則4-1-1】如果代碼行中的運(yùn)算符比較多,用括號(hào)確定表達(dá)式的操作順序,避免使用默認(rèn)的 優(yōu)先級(jí)。由于將表4-1熟記是比較困難的,為了防止產(chǎn)生歧義并提高可讀性,應(yīng)當(dāng)用括號(hào)確定表達(dá)式 的操作順序。例如:word = (high<<8)|low復(fù)合表達(dá)式如a=b=c=0這樣的表達(dá)式稱為復(fù)合表達(dá)式。允許復(fù)合表達(dá)式存在的理由是:(1)書寫簡(jiǎn)潔;(2)可以提高編譯效率。但要防止濫用復(fù)合表達(dá)式?!疽?guī)則4-2-1】不要編寫太復(fù)雜的復(fù)合表達(dá)式。例如:i=a
6、>=b&&c<d&&c+f<=g+h;/復(fù)合表達(dá)式過于復(fù)雜【規(guī)則4-2-2】不要有多用途的復(fù)合表達(dá)式。例如:d=(a=b+c)+r;該表達(dá)式既求a值又求d值。應(yīng)該拆分為兩個(gè)獨(dú)立的語(yǔ)句:a = b + c;d = a + r;【規(guī)則4-2-3】不要把程序中的復(fù)合表達(dá)式與“真正的數(shù)學(xué)表達(dá)式”混淆。例如:if(a<b<c)/a<b<c是數(shù)學(xué)表達(dá)式而不是程序表達(dá)式并不表示if (a<b)&&(b<c) 而是成了令人費(fèi)解的if(a<b)<c)語(yǔ)句if語(yǔ)句是C語(yǔ)言中最簡(jiǎn)單、最常用的語(yǔ)句,然而很
7、多程序員用隱含錯(cuò)誤的方式 寫if語(yǔ)句。本節(jié)以“與零值比較”為例,展開討論。布爾變量與零值比較【規(guī)則4-3-1】不可將布爾變量直接與 TRUE FALSER者1、0進(jìn)行比較。根據(jù)布爾類型的語(yǔ)義,零值為“假”(記為 FALSE,任何非零值都是“真”(記為 TRUE。TRUE勺值究竟是什么并沒有統(tǒng)一的標(biāo)準(zhǔn)。例如VisualC+將TRUE定義為1,而VisualBasic則將TRUE定義為-1。假設(shè)布爾變量名字為flag,它與零值比較的標(biāo)準(zhǔn)if語(yǔ)句如下:if (flag)/ 表示 flag 為真 if (flag)/ 表示 flag為假其它的用法都屬于不良風(fēng)格,例如:if(flag=TRUE) if(
8、flag=1) if(flag=FALSE) if(flag=0)整型變量與零值比較【規(guī)則 4-3-2】應(yīng)當(dāng)將整型變量用“ =”或“! =”直接與 0比較。假設(shè)整型 變量的名字為value,它與零值比較的標(biāo)準(zhǔn)if語(yǔ)句如下:if(value=0) if(value!=0)不可模仿布爾變量的風(fēng)格而寫成if(value)/會(huì)讓人誤解value是布爾變量 if(!value)浮點(diǎn)變量與零值比較【規(guī)則 4-3-3】不可將浮點(diǎn)變量用“ =”或“! =”與任何數(shù)字比較。千萬(wàn)要留意,無論是float還是double類型的變量,都有精度限制。所以一定要避免將浮點(diǎn)變 量用“ =”或“! =”與數(shù)字比較,應(yīng)該設(shè)法轉(zhuǎn)
9、化成“>=”或“ <=”形式。假設(shè)浮點(diǎn)變量的名字為 X,應(yīng)當(dāng)將 if(x=/ 隱含錯(cuò)誤的比較轉(zhuǎn)化為 if(X>=-EPSINON)&&(X<=EPSINON) 其中EPSINOr是允許的誤差(即精度)。指針變量與零值比較【規(guī)則 4-3-4】應(yīng)當(dāng)將指針變量用“ 指針變量的零值是 指針變量的名字為 p,if(p=NULL)=”或"!=”與NULL比較?!翱铡?記為NULL)。盡管NULL的值與0相同,但是兩者意義不同。假設(shè)它與零值比較的標(biāo)準(zhǔn)if語(yǔ)句如下:/p與NULL顯式比較,強(qiáng)調(diào)P是指針變量if(p!=NULL)不要寫成if(p=0)/容易讓人誤
10、解P是整型變量if(p!=0)或者if(p)/容易讓人誤解P是布爾變量if(!P)對(duì) if 語(yǔ)句的補(bǔ)充說明有時(shí)候我們可能會(huì)看到if(NULL=P)這樣古怪的格式。不是程序?qū)戝e(cuò)了,是程序員為了防止將if(p=NULL)誤寫成if(p=NULL),而有意把p和NULL顛倒。編譯器認(rèn)為if(p=NULL)是 合法的,但是會(huì)指出if(NULL=P)是錯(cuò)誤的,因?yàn)镹ULL不能被賦值。程序中有時(shí)會(huì)遇到 if/else/return 的組合,應(yīng)該將如下不良風(fēng)格的程序if(condition)returnx;returny;改寫為if(condition)returnx;elsereturny;或者改寫成更加
11、簡(jiǎn)練的return(conditionx:y);循環(huán)語(yǔ)句的效率C循環(huán)語(yǔ)句中,for語(yǔ)句使用頻率最高,while語(yǔ)句其次,do語(yǔ)句很少用。本節(jié)重點(diǎn)論述循環(huán) 體的效率。提高循環(huán)體效率的基本辦法是降低循環(huán)體的復(fù)雜性。【建議 4-4-1】在多重循環(huán)中,如果有可能,應(yīng)當(dāng)將最長(zhǎng)的循環(huán)放在最內(nèi)層,最短的循環(huán)放在最外層,以減少 CPU夸切循環(huán)層的次數(shù)。例如示例4-4(b)的效率比示例4-4(a)的高。for (row=0; row<100; row+)for (col=0; col<5; col+)fum = sum+arowcol;示例4-4(a)低效率:長(zhǎng)循環(huán)在最外層for (col=0; c
12、ol<5; col+)for (row=0; row<100; row+)fum = sum+arowcol;示例4-4(b)高效率:長(zhǎng)循環(huán)在最內(nèi)層【建議 4-4-2 】如果循環(huán)體內(nèi)存在邏輯判斷,并且循環(huán)次數(shù)很大,宜將邏輯判斷移到循環(huán)體 的外面。示例4-4(c)的程序比示例4-4(d)多執(zhí)行了 N-1次邏輯判斷。并且由于前者老要進(jìn)行邏輯判 斷,打斷了循環(huán)“流水線”作業(yè),使得編譯器不能對(duì)循環(huán)進(jìn)行優(yōu)化處理,降低了效率。如果N非常大,最好采用示例 4-4(d)的寫法,可以提高效率。如果 N非常小,兩者效率差別并不明顯, 采用示例4-4(c)的寫法比較好,因?yàn)槌绦蚋雍?jiǎn)潔。for (i=0
13、; i<N; i+)if (conditionDoSomething();elseDoOtherthing();表4-4(c)效率低但程序簡(jiǎn)潔if(condition)for(i=0;i<N;i+)DoSomething();elsefor(i=0;i<N;i+)DoOtherthing();表4-4(d)效率高但程序不簡(jiǎn)潔語(yǔ)句的循環(huán)控制變量【規(guī)則4-5-1】不可在for循環(huán)體內(nèi)修改循環(huán)變量,防止 for循環(huán)失去控制?!窘ㄗh 4-5-1 】建議 for 語(yǔ)句的循環(huán)控制變量的取值采用“半開半閉區(qū)間”寫法。示例4-5(a)中的X值屬于半開半閉區(qū)間“ 0=<x<N”,起
14、點(diǎn)到終點(diǎn)的間隔為 N,循環(huán)次數(shù)為N。 示例4-5(b)中的X值屬于閉區(qū)間“ 0=<x<=N-T,起點(diǎn)到終點(diǎn)的間隔為 N-1,循環(huán)次數(shù)為N。 相比之下,示例4-5(a)的寫法更加直觀,盡管兩者的功能是相同的。for(intx=0;x<N;x+)示例4-5(a)循環(huán)變量屬于半開半閉區(qū)間 for(intx=0;x<=N-1;x+)示例4-5(b)循環(huán)變量屬于閉區(qū)間語(yǔ)句switch是多分支選擇語(yǔ)句,而if語(yǔ)句只有兩個(gè)分支可供選擇。雖然可以用嵌套的if語(yǔ)句來實(shí)現(xiàn)多分支選擇,但那樣的程序冗長(zhǎng)難讀。這是switch語(yǔ)句存在的理由。switch語(yǔ)句的基本格式是:switch(varia
15、ble)casevalue1:break;casevalue2:break;default:break;【規(guī)則4-6-1】每個(gè)case語(yǔ)句的結(jié)尾不要忘了加 break,否則將導(dǎo)致多個(gè)分支重疊(除 非有意使多個(gè)分支重疊)?!疽?guī)則4-6-2】不要忘記最后那個(gè)default分支。即使程序真的不需要default處理,也應(yīng)該保留語(yǔ)句defaultbreak;這樣做并非多此一舉,而是為了防止別人誤以為你忘了default處理。語(yǔ)句自從提倡結(jié)構(gòu)化設(shè)計(jì)以來,goto就成了有爭(zhēng)議的語(yǔ)句。首先,由于goto語(yǔ)句可以靈活跳轉(zhuǎn),如果不加限制,它的確會(huì)破壞結(jié)構(gòu)化設(shè)計(jì)風(fēng)格。其次,goto語(yǔ)句經(jīng)常帶來錯(cuò)誤或隱患。它可能跳
16、過了某些對(duì)象的構(gòu)造、變量的初始化、重要的計(jì)算等語(yǔ)句,例如:goto String intstate;s1,s2; / 被 goto 跳過 sum = 0;/ 被 goto 跳過state:如果編譯器不能發(fā)覺此類錯(cuò)誤,每用一次goto語(yǔ)句都可能留下隱患。很多人建議廢除C的goto語(yǔ)句,以絕后患。但實(shí)事求是地說,錯(cuò)誤是程序員自己造成的, 不是goto的過錯(cuò)。goto語(yǔ)句至少有一處可顯神通,它能從多重循環(huán)體中咻地一下子跳到外 面,用不著寫很多次的 break 語(yǔ)句 ;例如gotoerror;error:就象樓房著火了,來不及從樓梯一級(jí)一級(jí)往下走,可從窗口跳出火坑。所以我們主張少 用、慎用 goto
17、語(yǔ)句,而不是禁用。第 5 章常量常量是一種標(biāo)識(shí)符,它的值在運(yùn)行期間恒定不變。C語(yǔ)言用#define來定義常量(稱為宏常量)。C+語(yǔ)言除了 #defi ne外還可以用const來定義常量(稱為con st常量)。為什么需要常量1)2)3)如果不使用常量,直接在程序中填寫數(shù)字或字符串,將會(huì)有什么麻煩程序的可讀性(可理解性)變差。程序員自己會(huì)忘記那些數(shù)字或字符串是什么意思,用 戶則更加不知它們從何處來、表示什么。在程序的很多地方輸入同樣的數(shù)字或字符串,難保不發(fā)生書寫錯(cuò)誤。如果要修改數(shù)字或字符串,則會(huì)在很多地方改動(dòng),既麻煩又容易出錯(cuò)?!疽?guī)則 5-1-1 】例如:#define constint con
18、stfloat盡量使用含義直觀的常量來表示那些將在程序中多次出現(xiàn)的數(shù)字或字符串。MAX 100/*C語(yǔ)言的宏常量*/MAX=100;/C+語(yǔ)言的 const常量Pl=;/C+語(yǔ)言的const常量與 #define的比較C+語(yǔ)言可以用 點(diǎn):(1)const來定義常量,也可以用 #define來定義常量。但是前者比后者有更多的優(yōu)con st常量有數(shù)據(jù)類型,而宏常量沒有數(shù)據(jù)類型。編譯器可以對(duì)前者進(jìn)行類型安全檢 查。而對(duì)后者只進(jìn)行字符替換,沒有類型安全檢查,并且在字符替換可能會(huì)產(chǎn)生意 料不到的錯(cuò)誤(邊際效應(yīng))。2)有些集成化的調(diào)試工具可以對(duì)con st常量進(jìn)行調(diào)試,但是不能對(duì)宏常量進(jìn)行調(diào)試。【規(guī)則5-
19、2-1】在C+程序中只使用const常量而不使用宏常量,即const常量完全取代宏常量。常量定義規(guī)則【規(guī)則 5-3-1】需要對(duì)外公開的常量放在頭文件中,不需要對(duì)外公開的常量放在定義文件的頭 部。為便于管理,可以把不同模塊的常量集中存放在一個(gè)公共的頭文件中?!疽?guī)則 5-3-2 】如果某一常量與其它常量密切相關(guān),應(yīng)在定義中包含這種關(guān)系,而不應(yīng)給出一些孤立的值。例如:const floatRADIUS=100;const floatDIAMETER=RADIUS*2;第 6 章函數(shù)設(shè)計(jì)函數(shù)是C程序的基本功能單元,其重要性不言而喻。函數(shù)設(shè)計(jì)的細(xì)微缺點(diǎn)很容易導(dǎo)致該函數(shù)被錯(cuò)用,所以光使函數(shù)的功能正確是不夠
20、的。本章重點(diǎn)論述函數(shù)的接口設(shè)計(jì)和內(nèi)部實(shí)現(xiàn)的一些規(guī)則。函數(shù)接口的兩個(gè)要素是參數(shù)和返回值。C語(yǔ)言中,函數(shù)的參數(shù)和返回值的傳遞方式有兩種:值傳遞(P assbyvalue)和指針傳遞(passby pointer)。C+語(yǔ)言中多了引用傳遞(passbyrefere nee)。由于引用傳遞的性質(zhì)象指針傳遞,而使用方式卻象值傳遞,初學(xué)者常 常迷惑不解,容易引起混亂,請(qǐng)先閱讀節(jié)“引用與指針的比較”。參數(shù)的規(guī)則【規(guī)則 6-1-1】參數(shù)的書寫要完整,不要貪圖省事只寫參數(shù)的類型而省略參數(shù)名字。如果函 數(shù)沒有參數(shù),則用 void 填充。例如:void SetValue(int width, int height)
21、;/ 良好的風(fēng)格/ 不良的風(fēng)格/ 良好的風(fēng)格/ 不良的風(fēng)格void SetValue(int,int);float GetValue(void);float GetValue();順序要合理?!疽?guī)則 6-1-2】參數(shù)命名要恰當(dāng),例如編寫字符串拷貝函數(shù)StringCopy,它有兩個(gè)參數(shù)。如果把參數(shù)名字起為str1和str2,例如void StringCopy(char *str1,char *str2);那么我們很難搞清楚究竟是把str1拷貝到str2中,還是剛好倒過來。可以把參數(shù)名字起得更有意義,如叫strSource和strDestination。這樣從名字上就可以看出應(yīng)該把 strSour
22、ce 拷貝到 strDestination。還有一個(gè)問題,這兩個(gè)參數(shù)那一個(gè)該在前那一個(gè)該在后參數(shù)的順序要遵循程序員的習(xí)慣。 一般地,應(yīng)將目的參數(shù)放在前面,源參數(shù)放在后面。如果將函數(shù)聲明為:void StringCopy(char *strSource,char *strDestination); 別人在使用時(shí)可能會(huì)不假思索地寫成如下形式:char str20;StringCopy(str,“ HelloWorld ”);/ 參數(shù)順序顛倒const ,以防止該指針在函const& ”方式來傳遞,【規(guī)則 6-1-3 】如果參數(shù)是指針,且僅作輸入用,則應(yīng)在類型前加 數(shù)體內(nèi)被意外修改。例如:v
23、oid StringCopy(char *strDestination , const char *strSource);【規(guī)則 6-1-4 】如果輸入?yún)?shù)以值傳遞的方式傳遞對(duì)象,則宜改用“ 這樣可以省去臨時(shí)對(duì)象的構(gòu)造和析構(gòu)過程,從而提高效率?!窘ㄗh 6-1-1】避免函數(shù)有太多的參數(shù),參數(shù)個(gè)數(shù)盡量控制在5個(gè)以內(nèi)。如果參數(shù)太多,在使用時(shí)容易將參數(shù)類型或順序搞錯(cuò)。【建議 6-1-2 】盡量不要使用類型和數(shù)目不確定的參數(shù)。C標(biāo)準(zhǔn)庫(kù)函數(shù)printf是采用不確定參數(shù)的典型代表,其原型為:int pnntf(const ehat *format,argument );這種風(fēng)格的函數(shù)在編譯時(shí)喪失了嚴(yán)格的類型
24、安全檢查。返回值的規(guī)則【規(guī)則 6-2-1 】不要省略返回值的類型。C語(yǔ)言中,凡不加類型說明的函數(shù),一律自動(dòng)按整型處理。這樣做不會(huì)有什么好處,卻容易 被誤解為void類型。C+語(yǔ)言有很嚴(yán)格的類型安全檢查,不允許上述情況發(fā)生。由于C+程序可以調(diào)用C函數(shù),為了避免混亂,規(guī)定任何C+/C函數(shù)都必須有類型。如果函數(shù)沒有返回值,那么應(yīng)聲明為void類型?!疽?guī)則 6-2-2】函數(shù)名字與返回值類型在語(yǔ)義上不可沖突。違反 這條規(guī)則的典型代表是 C標(biāo)準(zhǔn)庫(kù)函數(shù)getchar。例如:charc;c=getchar();if(c=EOF)按照getchar名字的意思,將變量c聲明為char類型是很自然的事情。但不幸的是
25、 getchar的確不是char類型,而是int類型,其原型如下:int getchar(void);由于C是char類型,取值范圍是-128,127,如果宏EOF勺值在char的取值范圍之外,那 么if語(yǔ)句將總是失敗,這種“危險(xiǎn)”人們一般哪里料得到!導(dǎo)致本例錯(cuò)誤的責(zé)任并不在用 戶,是函數(shù)getchar誤導(dǎo)了使用者?!疽?guī)則 6-2-3 】不要將正常值和錯(cuò)誤標(biāo)志混在一起返回。正常值用輸出參數(shù)獲得,而錯(cuò)誤標(biāo) 志用 return 語(yǔ)句返回?;仡櫳侠?,C標(biāo)準(zhǔn)庫(kù)函數(shù)的設(shè)計(jì)者為什么要將getchar聲明為令人迷糊的int類型呢他會(huì)那么傻嗎getchar碰到文件結(jié)束標(biāo)志或發(fā)生讀錯(cuò) 只好將EOF定義為負(fù)數(shù)在正
26、常情況下,getchar的確返回單個(gè)字符。但如果 誤,它必須返回一個(gè)標(biāo)志 EOF。為了區(qū)別于正常的字符,為了避免出現(xiàn)誤解,我們應(yīng)該將return 語(yǔ)句返回。(通常為負(fù)1)。因此函數(shù)getchar就成了 int類型。 我們?cè)趯?shí)際工作中,經(jīng)常會(huì)碰到上述令人為難的問題。正常值和錯(cuò)誤標(biāo)志分開。即:正常值用輸出參數(shù)獲得,而錯(cuò)誤標(biāo)志用函數(shù) getchar可以改寫成 BOOL GetChar(char *c);雖然gechar比GetChar靈活,例如putchar(getchar();但是如果getchar用錯(cuò)了,它的靈活性又 有什么用呢【建議 6-2-1】有時(shí)候函數(shù)原本不需要返回值,但為了增加靈活性如支
27、持鏈?zhǔn)奖磉_(dá),可以附 加返回值。例如字符串拷貝函數(shù)strcpy的原型:char *strcpy(char *strDest , const char *strSrc);strcpy函數(shù)將strSrc拷貝至輸出參數(shù)strDest中,同時(shí)函數(shù)的返回值又是strDest。這樣做并非多此一舉,可以獲得如下靈活性:charstr20;HelloWorld ” );int length=strlen(strcpy(str,建議 6-2-2】如果函數(shù)的返回值是一個(gè)對(duì)象,有些場(chǎng)合用“引用傳遞”替換“值傳遞”可以提高效率。而有些場(chǎng)合只能用“值傳遞”而不能用“引用傳遞”,否則會(huì)出錯(cuò)。 例如:class String
28、/ 賦值函數(shù)String &operate=(const String &other);/ 相加函數(shù),如果沒有 friend 修飾則只許有一個(gè)右側(cè)參數(shù)friend String operate+(const String &s1,const String &s2);private:char*m_data;String 的賦值函數(shù) operate= 的實(shí)現(xiàn)如下:String &String:operate=(const String &other)if(this=&other)return*this;deletem_data;m_data=
29、newcharstrlen+1;strcpy(m_data,;return*this;/ 返回的是 *this 的引用,無需拷貝過程對(duì)于賦值函數(shù),應(yīng)當(dāng)用“引用傳遞”的方式返回Stri ng對(duì)象。如果用“值傳遞”的方式,雖然功能仍然正確,但由于 return 語(yǔ)句要把 *this 拷貝到保存返回值的外部存儲(chǔ)單元之 中,增加了不必要的開銷,降低了賦值函數(shù)的效率。例如:Stringa,b,c;a=b;a=b=c;/ 如果用“值傳遞”,將產(chǎn)生一次/ 如果用“值傳遞”,將產(chǎn)生兩次*this 拷貝*this 拷貝Stri ng的相加函數(shù)operate+ 的實(shí)現(xiàn)如下:String operate+(cons
30、t String &s1,const String &s2)String temp;/ 是僅含 0'的字符串=newcharstrlen+strlen+1;strcpy,;strcat,;return temp;對(duì)于相加函數(shù),應(yīng)當(dāng)用“值傳遞”的方式返回Stri ng對(duì)象。如果改用“引用傳遞”,那么函數(shù)返回值是一個(gè)指向局部對(duì)象temp的“引用”。由于temp在函數(shù)結(jié)束時(shí)被自動(dòng)銷毀,將導(dǎo)致返回的“引用”無效。例如:c=a+b;此時(shí)a+b并不返回期望值,C什么也得不到,流下了隱患。函數(shù)內(nèi)部實(shí)現(xiàn)的規(guī)則不同功能的函數(shù)其內(nèi)部實(shí)現(xiàn)各不相同,看起來似乎無法就“內(nèi)部實(shí)現(xiàn)”達(dá)成一致的觀 點(diǎn)
31、。但根據(jù)經(jīng)驗(yàn),我們可以在函數(shù)體的“入口處”和“出口處”從嚴(yán)把關(guān),從而提高函數(shù)的 質(zhì)量?!疽?guī)則 6-3-1 】在函數(shù)體的“入口處”,對(duì)參數(shù)的有效性進(jìn)行檢查。assert)來防很多程序錯(cuò)誤是由非法參數(shù)引起的,我們應(yīng)該充分理解并正確使用“斷言”( 止此類錯(cuò)誤。詳見節(jié)“使用斷言”?!疽?guī)則 6-3-2】在函數(shù)體的“出口處”,對(duì) return 語(yǔ)句的正確性和效率進(jìn)行檢查。如果函數(shù)有返回值,那么函數(shù)的“出口處”是return語(yǔ)句。我們不要輕視r(shí)eturn語(yǔ)句。如果return 語(yǔ)句寫得不好,函數(shù)要么出錯(cuò),要么效率低下。注意事項(xiàng)如下:(1) return 語(yǔ)句不可返回指向“棧內(nèi)存”的“指針”或者“引用”,因?yàn)?/p>
32、該內(nèi)存在函數(shù)體結(jié)束 時(shí)被自動(dòng)銷毀。例如char *Func(void) return String(s1+s2);char str="helloworld的內(nèi)存位于棧上return str;/將導(dǎo)致錯(cuò)誤2) 要搞清楚返回的究竟是3) 如果函數(shù)返回值是一個(gè)對(duì)象,值”、“指針”還是“引用”。要考慮 return 語(yǔ)句的效率。例如這是臨時(shí)對(duì)象的語(yǔ)法,表示“創(chuàng)建一個(gè)臨時(shí)對(duì)象并返回它”。不要以為它與“先創(chuàng)建一個(gè) 局部對(duì)象 temp 并返回它的結(jié)果”是等價(jià)的,如String temp(s1+s2);return temp;實(shí)質(zhì)不然,上述代碼將發(fā)生三件事。首先, temp 對(duì)象被創(chuàng)建,同時(shí)完成初始
33、化;然后拷 貝構(gòu)造函數(shù)把temp拷貝到保存返回值的外部存儲(chǔ)單元中;最后,temp在函數(shù)結(jié)束時(shí)被銷毀(調(diào)用析構(gòu)函數(shù))。然而“創(chuàng)建一個(gè)臨時(shí)對(duì)象并返回它”的過程是不同的,編譯器直接把臨 時(shí)對(duì)象創(chuàng)建并初始化在外部存儲(chǔ)單元中,省去了拷貝和析構(gòu)的化費(fèi),提高了效率。類似地,我們不要將return int(x+y);/ 創(chuàng)建一個(gè)臨時(shí)變量并返回它寫成int temp=x+y;return temp;由于內(nèi)部數(shù)據(jù)類型如 int,float,double 的變量不存在構(gòu)造函數(shù)與析構(gòu)函數(shù),雖然該“臨時(shí)變量 的語(yǔ)法”不會(huì)提高多少效率,但是程序更加簡(jiǎn)潔易讀。函數(shù)的功能要單一,不要設(shè)計(jì)多用途的函數(shù)。 函數(shù)體的規(guī)模要小,盡量
34、控制在50行代碼之內(nèi)。盡量避免函數(shù)帶有“記憶”功能。相同的輸入應(yīng)當(dāng)產(chǎn)生相同的輸出。帶有“記其它建議【建議 6-4-1 】【建議 6-4-2 】【建議 6-4-3 】 憶”功能的函數(shù),其行為可能是不可預(yù)測(cè)的,因?yàn)樗男袨榭赡苋Q于某種“記憶狀態(tài)”。這樣的函數(shù)既不易理解又不利于測(cè)試和維護(hù)。在C/C+語(yǔ)言中,函數(shù)的static局部變量是函數(shù)的“記憶”存儲(chǔ)器。建議盡量少用static局部變量,除非必需?!窘ㄗh 6-4-4】不僅要檢查輸入?yún)?shù)的有效性,還要檢查通過其它途徑進(jìn)入函數(shù)體內(nèi)的變量 的有效性,例如全局變量、文件句柄等?!窘ㄗh 6-4-5】用于出錯(cuò)處理的返回值一定要清楚,讓使用者不容易忽視或誤解錯(cuò)
35、誤情況。使用斷言程序一般分為Debug版本和Release版本,Debug版本用于內(nèi)部調(diào)試,Release版本發(fā)行給用 戶使用。斷言assert是僅在Debug版本起作用的宏,它用于檢查“不應(yīng)該”發(fā)生的情況。示 例6-5是一個(gè)內(nèi)存復(fù)制函數(shù)。在運(yùn)行過程中,如果assert的參數(shù)為假,那么程序就會(huì)中止(一般assert)。void地還會(huì)出現(xiàn)提示對(duì)話,說明在什么地方引發(fā)了*memcpy(void *pvTo,const void *pvFrom,size_t size)assert(pvTo!=NULL)&&(pvFrom!=NULL);/ 使用斷言/防止改變pvTo的地址/防止改變
36、 pvFrom 的地址byte*pbTo=(byte*)pvTo;byte*pbFrom=(byte*)pvFrom;while(size->0)*pbTo+=*pbFrom+;returnpvTo;示例 6-5復(fù)制不重疊的內(nèi)存塊assert不是一個(gè)倉(cāng)促拼湊起來的宏。為了不在程序的Debug版本和Release版本引起差另h assert不應(yīng)該產(chǎn)生任何副作用。所以assert不是函數(shù),而是宏。程序員可以把a(bǔ)ssert看成一個(gè)在任何系統(tǒng)狀態(tài)下都可以安全使用的無害測(cè)試手段。如果程序在assert處終止了,并不是說含有該assert的函數(shù)有錯(cuò)誤,而是調(diào)用者出了差錯(cuò),assert可以幫助我們找到
37、發(fā)生錯(cuò)誤的原因。很少有比跟蹤到程序的斷言,卻不知道該斷言的作用更讓人沮喪的事了。你化了很多時(shí)間,不是為了排除錯(cuò)誤,而只是為了弄清楚這個(gè)錯(cuò)誤到底是什么。有的時(shí)候,程序員偶爾還會(huì)設(shè)計(jì)出 有錯(cuò)誤的斷言。所以如果搞不清楚斷言檢查的是什么,就很難判斷錯(cuò)誤是出現(xiàn)在程序中,還是 出現(xiàn)在斷言中。幸運(yùn)的是這個(gè)問題很好解決,只要加上清晰的注釋即可。這本是顯而易見的事 情,可是很少有程序員這樣做。這好比一個(gè)人在森林里,看到樹上釘著一塊“危險(xiǎn)”的大牌 子。但危險(xiǎn)到底是什么樹要倒有廢井有野獸除非告訴人們“危險(xiǎn)”是什么,否則這個(gè)警告牌難 以起到積極有效的作用。難以理解的斷言常常被程序員忽略,甚至被刪除。【規(guī)則 6-5-1 】使用斷言捕捉不應(yīng)該發(fā)生的非法情況。不要混淆非法情況與錯(cuò)誤情況 之間的區(qū)別,后者是必然存在的并且是一定要作出處理的?!疽?guī)則 6-5-2】在函數(shù)的入口處,使用斷言檢查參數(shù)的有效性(合法性)?!窘ㄗh 6-5-1 】在編寫函數(shù)時(shí),要進(jìn)行反復(fù)的考查,并且自問:“我打算做哪些假定”一旦 確定了的假定,就要使用斷言對(duì)假定進(jìn)行檢查?!窘ㄗh 6-5-2】一般教科書都鼓勵(lì)程序員們進(jìn)行防錯(cuò)設(shè)計(jì),但要記住這種編程風(fēng)格可能會(huì) 隱瞞錯(cuò)誤。當(dāng)進(jìn)行防錯(cuò)設(shè)計(jì)時(shí),如果“不可能發(fā)生”的事情的確發(fā)生了,則要使用斷言 進(jìn)行報(bào)警。引用與指針的比較弓I用是C+中的
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 鋼筋工勞務(wù)合同的履約管理
- 環(huán)保型頂管施工方案探討
- 海洋工程石方爆破實(shí)施方案
- 家庭教育與隨班就讀相結(jié)合的制度
- 醫(yī)療器械供應(yīng)方案與合規(guī)措施
- 物流中心消火栓滅火系統(tǒng)維修方案
- 科技公司知識(shí)產(chǎn)權(quán)公開制度
- 商業(yè)綜合體綠化與景觀設(shè)計(jì)方案
- 學(xué)前教育專業(yè)人才培養(yǎng)方案調(diào)研報(bào)告
- 浙科版生物學(xué)高一上學(xué)期期末試卷與參考答案
- 高中美術(shù)-抽象藝術(shù)教學(xué)課件設(shè)計(jì)
- 啄木鳥糾錯(cuò)活動(dòng)方案(八篇)
- 出口退稅知識(shí)培訓(xùn)
- 某水利工程引水隧洞重大設(shè)計(jì)變更索賠報(bào)告
- 山東省青島市青島第二中學(xué)2024年高三物理第一學(xué)期期中聯(lián)考模擬試題含解析
- 大學(xué)辦公室管理制度公司管理制度
- 牛津譯林版八年級(jí)英語(yǔ)上冊(cè)Unit 7 Seasons Grammar 示范公開課教學(xué)課件
- 居家養(yǎng)老服務(wù)管理(社區(qū)居家養(yǎng)老服務(wù)課件)
- 妊娠合并癥 妊娠合并心臟?。▼D產(chǎn)科護(hù)理課件)
- QC小組活動(dòng)程序講解(自定目標(biāo)值類型)
- 市民中心信息系統(tǒng)運(yùn)營(yíng)維護(hù)方案
評(píng)論
0/150
提交評(píng)論