版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
C語言書寫規(guī)范指南第1章文件結(jié)構(gòu)每個C程序通常分為兩個文件。一個文件用于保存程序的聲明(declaration),稱為頭文件。另一個文件用于保存程序的實現(xiàn)(implementation),稱為定義(definition)文件。C程序的頭文件以“.h”為后綴,C程序的定義文件以“.c”為后綴。1.1版權(quán)和版本的聲明版權(quán)和版本的聲明位于頭文件和定義文件的開頭(參見示例1-1),主要內(nèi)容有(1)版權(quán)信息。(2)文件名稱,標識符,摘要。(3)當前版本號,作者/修改者,完成日期。(4)版本歷史信息。/**Copyright(c)2001,吉林大學(xué)物理學(xué)院無線電*Allrightsreserved.**文件名稱:filename.h*文件標識:*摘要:簡要描述本文件的內(nèi)容**當前版本:1.1*作者:輸入作者(或修改者)名字*完成日期:2007年7月20日**取代版本:1.0*原作者:輸入原作者(或修改者)名字*完成日期:2007年5月10日*/示例1-1版權(quán)和版本的聲明1.2頭文件的結(jié)構(gòu)頭文件由三部分內(nèi)容組成:1)頭文件開頭處的版權(quán)和版本聲明(參見示例1-1)。2)預(yù)處理塊。3)函數(shù)和類結(jié)構(gòu)聲明等。假設(shè)頭文件名稱為SCL_SPI.h,頭文件的結(jié)構(gòu)參見示例1-2?!疽?guī)則1-2T】為了防止頭文件被重復(fù)引用,應(yīng)當用#ifndef/#define/#endif結(jié)構(gòu)產(chǎn)生預(yù)處理塊?!疽?guī)則1-2-2】用#include〈filename.h〉格式來引用標準庫的頭文件(編譯器將從標準庫目錄開始搜索)?!疽?guī)則1-2-3】用#include“filename.h”格式來引用非標準庫的頭文件(編譯器將從用戶的工作目錄開始搜索)?!疽?guī)則1-2-4】#include后面使用TAB鍵控制排版?!疽?guī)則1-2-5】頭文件中只存放“聲明”而不存放“定義”【規(guī)則1-2-6】全局變量在頭文件中聲明,在.c文件中定義.hexternintvalue;聲明。.cintvalue=0x10;定義?!疽?guī)則1-2-7】局部變量在.c中定義(static)unsignedintvalue;定義。//版權(quán)和版本聲明見示例1-1,此處省略。#ifndefSCL_SPI_H//防止SCL_SPI.h被重復(fù)引用#defineSCL_SPI_H#include〈p30f6014A.h〉//引用標準庫的頭文件???#include“SCL_CAN.h”//引用非標準庫的頭文件voidFunction1(…);//全局函數(shù)聲明???externunsignintvalue;//全局變量聲明#endif示例1-2C頭文件的結(jié)構(gòu)1.3定義文件的結(jié)構(gòu)定義文件有三部分內(nèi)容:1)定義文件開頭處的版權(quán)和版本聲明(參見示例1-1)2)對一些頭文件的引用。3)程序的實現(xiàn)體(包括數(shù)據(jù)和代碼)。假設(shè)定義文件的名稱為SCL_SPI.c,定義文件的結(jié)構(gòu)參見示例1-3。//版權(quán)和版本聲明見示例1-1,此處省略。#include“SCL_SPI.h”//引用頭文件???//全局變量定義unsignintvalue=0x10;//全局函數(shù)的實現(xiàn)體voidFunction1(…){???}示例1-3C定義文件的結(jié)構(gòu)1.4頭文件的作用早期的編程語言如Basic、Fortran沒有頭文件的概念,C語言的初學(xué)者雖然會用使用頭文件,但常常不明其理。這里對頭文件的作用略作解釋:(1)通過頭文件來調(diào)用庫功能。在很多場合,源代碼不便(或不準)向用戶公布,只要向用戶提供頭文件和二進制的庫即可。用戶只需要按照頭文件中的接口聲明來調(diào)用庫功能,而不必關(guān)心接口怎么實現(xiàn)的。編譯器會從庫中提取相應(yīng)的代碼。(2)頭文件能加強類型安全檢查。如果某個接口被實現(xiàn)或被使用時,其方式與頭文件中的聲明不一致,編譯器就會指出錯誤,這一簡單的規(guī)則能大大減輕程序員調(diào)試、改錯的負擔。1.5目錄結(jié)構(gòu)如果一個軟件的頭文件數(shù)目比較多(如超過十個),通常應(yīng)將頭文件和定義文件分別保存于不同的目錄,以便于維護。例如可將頭文件保存于include目錄,將定義文件保存于source目錄(可以是多級目錄)。如果某些頭文件是私有的,它不會被用戶的程序直接引用,則沒有必要公開其“聲明”。為了加強信息隱藏,這些私有的頭文件可以和定義文件存放于同一個目錄。第2章程序的版式版式雖然不會影響程序的功能,但會影響可讀性。程序的版式追求清晰、美觀,是程序風格的重要構(gòu)成因素??梢园殉绦虻陌媸奖扔鳛椤皶ā?。好的“書法”可讓人對程序一目了然,看得興致勃勃。差的程序“書法”如螃蟹爬行,讓人看得索然無味,更令維護者煩惱有加。請程序員們學(xué)習程序的“書法”,彌補大學(xué)計算機教育的漏洞,實在很有必要。2.1空行空行起著分隔程序段落的作用??招械皿w(不過多也不過少)將使程序的布局更加清晰??招胁粫速M內(nèi)存,雖然打印含有空行的程序是會多消耗一些紙張,但是值得。所以不要舍不得用空行?!疽?guī)則2-1-1]在每個函數(shù)定義結(jié)束之后都要加空行。參見示例2-1(a)【規(guī)則2-1-2】在一個函數(shù)體內(nèi),邏揖上密切相關(guān)的語句之間不加空行,其它地方應(yīng)加空行分隔。參見示例2-1(b)//空行voidFunction1(…){}//空行voidFunction2(…){}示例2-1(a)函數(shù)之間的空行//空行while(condition){statement1;//空行if(condition){statement2;}elsestatement3;}//空行statement4;}示例2T(b)函數(shù)內(nèi)部的空行2.2代碼行【規(guī)則2-2-1】一行代碼只做一件事情,如只定義一個變量,或只寫一條語句。這樣的代碼容易閱讀,并且方便于寫注釋?!疽?guī)則2-2-2]if、for、while、do等語句自占一行,執(zhí)行語句不得緊跟其后。不論執(zhí)行語句有多少都要加{}。這樣可以防止書寫失誤。示例2-2(a)為風格良好的代碼行,示例2-2(b)為風格不良的代碼行。intwidth;//寬度intheight;//高度intdepth;//深度中間使用TAB鍵控制距離intwidth,height,depth;//寬度高度深度x=a+b;//等號左右用空格控制距離y=c+d;z=e+f;x=a+b;y=c+d;z=e+f;if(width<height)//<左右用空格控制距離{dosomething();//使用TAB鍵控制距離}if(width〈height)dosomething();for(initialization;condition;update){dosomething();//使用TAB鍵控制距離}//空行other();for(initialization;condition;update)dosomething();other();示例2-2(a)風格良好的代碼行示例2-2(b)風格不良的代碼行【建議2-2-1】盡可能在定義變量的同時初始化該變量(就近原則)如果變量的引用處和其定義處相隔比較遠,變量的初始化很容易被忘記。如果引用了未被初始化的變量,可能會導(dǎo)致程序錯誤。本建議可以減少隱患。例如intwidth=10;//定義并初紿化widthintheight=10;//定義并初紿化heightintdepth=10;//定義并初紿化depth使用TAB鍵控制距離2?3代碼行內(nèi)的空格【規(guī)則2-3-1]關(guān)鍵字之后要留空格。象const、virtual、inline、case等關(guān)鍵字之后至少要留一個空格,否則無法辨析關(guān)鍵字。象if、for、while等關(guān)鍵字之后應(yīng)留一個空格再跟左括號'(',以突出關(guān)鍵字?!疽?guī)則2-3-2]函數(shù)名之后不要留空格,緊跟左括號'(',以與關(guān)鍵字區(qū)別?!疽?guī)則2-3-3]'('向后緊跟,‘)'、','、';'向前緊跟,緊跟處不留空格?!疽?guī)則2-3-4]','之后要留空格,如Function(x,y,z)。如果';'不是一行的結(jié)束符號,其后要留空格,如for(initialization;condition;update)?!疽?guī)則2-3-5]賦值操作符、比較操作符、算術(shù)操作符、邏輯操作符、位域操作符,如“=”、“+=”“〉=”、“〈=”、“+”、“*”、“%”、“&&”、“||”、“〈〈”,“?”等二元操作符的前后應(yīng)當加空格?!疽?guī)則2-3-6]一元操作符如“!”、“~”、“++”、“—”、“&”(地址運算符)等前后不加空格?!疽?guī)則2-3-7】象“[]”、“.”、“-〉”這類操作符前后不加空格。【建議2-3-1]對于表達式比較長的for語句和if語句,為了緊湊起見可以適當?shù)厝サ粢恍┛崭?,如for(i=0;i〈10;i++)和if((a<=b)&&(c<=d))voidFunc1(intx,inty,intz);voidFuncl(intx,inty,intz);//良好的風格//不良的風格if(year>=2000)//良好的風格辻(year〉=2000)//不良的風格辻((a〉二b)&&(c<=d))//良好的風格if(a>=b&&c<=d)//不良的風格for(i=0;i<10;i++)//良好的風格for(i=0;i〈10;i++)//不良的風格for(I=0;I<10;I++)//過多的空格x=a<b?a:b;//良好的風格x=a〈b?a:b;//不好的風格int*x=&y;//良好的風格int*x=&y;//不良的風格array[5]=0;//不要寫成array[5]=0;a.Function();//不要寫成a.Function();b->Function();//不要寫成b->Function();示例2-3代碼行內(nèi)的空格2.4對齊【規(guī)則2-4-1]程序的分界符'{'和'}'應(yīng)獨占一行并且位于同一列,同時與引用它們的語句左對齊?!疽?guī)則2-4-2]{}之內(nèi)的代碼塊在'{'右邊一個TAB鍵處左對齊。示例2-4(a)為風格良好的對齊,示例2-4(b)為風格不良的對齊。
voidFunction(intx)VoidFunction(intx){?"http://programcode}{}…//programcodeif({condition)if(condition){…//programcode…//programcode}else{}else{}…//programcode…//programcode}for{}(initialization;condition;update)for(initialization;condition;update){…//programcode…//programcode}while(condition)while(condition){{}…//programcode…//programcode}如果出現(xiàn)嵌套的{},則使用縮進對齊,如:{{}}示例2-4(a)風格良好的對齊示例2-4(b)風格不良的對齊2.5長行拆分【規(guī)則2-5-1]代碼行最大長度宜控制在70至80個字符以內(nèi)。代碼行不要過長,否則眼睛看不過來,也不便于打印?!疽?guī)則2-5-2】長表達式要在低優(yōu)先級操作符處拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要進行適當?shù)目s進,使排版整齊,語句可讀。if((very_longer_variablel>=very_longer_variablel2)&&(very_longer_variable3<=very_longer_variable14)使用tab鍵控制距離&&(very_longer_variable5<=very_longer_variable16)){dosomething();}VirtualCMatrixCMultiplyMatrix(CMatrixleftMatrix,CMatrixrightMatrix);使用TAB鍵控制距離For(very_longer_initialization;very_longer_condition;使用TAB鍵控制距離very_longer_update){dosomething();}示例2-5長行的拆分2.6修飾符的位置修飾符*和&應(yīng)該靠近數(shù)據(jù)類型還是該靠近變量名,是個有爭議的活題。若將修飾符*靠近數(shù)據(jù)類型,例如:int*x;從語義上講此寫法比較直觀,即x是int類型的指針。上述寫法的弊端是容易引起誤解,例如:int*x,y;此處y容易被誤解為指針變量。雖然將x和y分行定義可以避免誤解,但并不是人人都愿意這樣做?!疽?guī)則2-6-1】應(yīng)當將修飾符*和&緊靠變量名例如:char*name;int*x,y;//此處y不會被誤解為指針2.7注釋C語言的注釋符為“/*???*/”。C++語言中,程序塊的注釋常采用“/*???*/”,行注釋一般采用“//???”。注釋通常用于:版本、版權(quán)聲明;函數(shù)接口說明;重要的代碼行或段落提示。雖然注釋有助于理解代碼,但注意不可過多地使用注釋。參見示例2-6?!疽?guī)則2-7-1】注釋是對代碼的“提示”,而不是文檔。程序中的注釋不可喧賓奪主,注釋太多了會讓人眼花繚亂。注釋的花樣要少?!疽?guī)則2-7-2】如果代碼本來就是清楚的,則不必加注釋。否則多此一舉,令人厭煩。例如i++;//i加1,多余的注釋【規(guī)則2-7-3】邊寫代碼邊注釋,修改代碼同時修改相應(yīng)的注釋,以保證注釋與代碼的一致性。不再有用的注釋要刪除?!疽?guī)則2-7-4】注釋應(yīng)當準確、易懂,防止注釋有二義性。錯誤的注釋不但無益反而有害?!疽?guī)則2-7-5】盡量避免在注釋中使用縮寫,特別是不常用縮寫?!疽?guī)則2-7-6】注釋的位置應(yīng)與被描述的代碼相鄰,可以放在代碼的上方或右方,不可放在下方?!疽?guī)則2-7-8】當代碼比較長,特別是有多重嵌套時,應(yīng)當在一些段落的結(jié)束處加注釋,便于閱讀。/**函數(shù)介紹:*輸入?yún)?shù):*輸出參數(shù):*返回值:*/VoidFunction(floatx,floaty,floatz){???if(…){while(…){}//endofwhile}//endofif}示例2-6程序的注釋第3章命名規(guī)則比較著名的命名規(guī)則當推Microsoft公司的“匈牙利”法,該命名規(guī)則的主要思想是“在變量和函數(shù)名中加入前綴以增進人們對程序的理解”。例如所有的字符變量均以ch為前綴,若是指針變量則追加前綴p。如果一個變量由ppch開頭,則表明它是指向字符指針的指針?!靶傺览狈ㄗ畲蟮娜秉c是煩瑣,例如inti,j,k;floatx,y,z;倘若采用“匈牙利”命名規(guī)則,則應(yīng)當寫成intii,ij,ik;//前綴i表示int類型floatfX,fY,fZ;//前綴f表示float類型如此煩瑣的程序會讓絕大多數(shù)程序員無法忍受。據(jù)考察,沒有一種命名規(guī)則可以讓所有的程序員贊同,程序設(shè)計教科書一般都不指定命名規(guī)則。命名規(guī)則對軟件產(chǎn)品而言并不是“成敗悠關(guān)”的事,我們不要化太多精力試圖發(fā)明世界上最好的命名規(guī)則,而應(yīng)當制定一種令大多數(shù)項目成員滿意的命名規(guī)則,并在項目中貫徹實施。絕對杜絕漢語拼音命名法3.1共性規(guī)則本節(jié)論述的共性規(guī)則是被大多數(shù)程序員采納的,我們應(yīng)當在遵循這些共性規(guī)則的前提下,再擴充特定的規(guī)則,如3.2節(jié)?!疽?guī)則3-1-1]標識符應(yīng)當直觀且可以拼讀,可望文知意,不必進行“解碼”。標識符最好采用英文單詞或其組合,便于記憶和閱讀。切忌使用漢語拼音來命名。程序中的英文單詞一般不會太復(fù)雜,用詞應(yīng)當準確。例如不要把CurrentValue寫成NowValue?!疽?guī)則3-1-2]標識符的長度應(yīng)當符合“min-length&&max-information”原則。幾十年前老ANSIC規(guī)定名字不準超過6個字符,現(xiàn)今的C不再有此限制。一般來說,長名字能更好地表達含義,所以函數(shù)名、變量名、類名長達十幾個字符不足為怪。那么名字是否越長約好?不見得!例如變量名maxval就比maxValueUntilOverflow好用。單字符的名字也是有用的,常見的如i,j,k,m,n,x,y,z等,它們通常可用作函數(shù)內(nèi)的局部變量?!疽?guī)則3-1-3]命名規(guī)則盡量與所采用的操作系統(tǒng)或開發(fā)工具的風格保持一致。例如Windows應(yīng)用程序的標識符通常采用“大小寫”混排的方式,如AddChild。而Unix應(yīng)用程序的標識符通常采用“小寫加下劃線”的方式,如add_child。別把這兩類風格混在一起用。【規(guī)則3-1-4]程序中不要出現(xiàn)僅靠大小寫區(qū)分的相似的標識符。例如:intx,X;//變量x與X容易混淆voidfoo(intx);//函數(shù)foo與FOO容易混淆voidFOO(floatx);【規(guī)則3-1-5]程序中不要出現(xiàn)標識符完全相同的局部變量和全局變量,盡管兩者的作用域不同而不會發(fā)生語法錯誤,但會使人誤解?!疽?guī)則3-1-6]變量的名字應(yīng)當使用“名詞”或者“形容詞+名詞”。例如:floatvalue;floatoldValue;floatnewValue;【規(guī)則3-1-7]全局函數(shù)的名字應(yīng)當使用“動詞”或者“動詞+名詞”(動賓詞組)。類的成員函數(shù)應(yīng)當只使用“動詞”,被省略掉的名詞就是對象本身。例如:DrawBox();//全局函數(shù)box-〉Draw();//類的成員函數(shù)【規(guī)則3-1-8】用正確的反義詞組命名具有互斥意義的變量或相反動作的函數(shù)等。例如:intminValue;intmaxValue;intintSetValue(…);intintGetValue(…);【建議3-1-1】盡量避免名字中出現(xiàn)數(shù)字編號,如Value1,Value2等,除非邏輯上的確需要編號。這是為了防止程序員偷懶,不肯為命名動腦筋而導(dǎo)致產(chǎn)生無意義的名字(因為用數(shù)字編號最省事)。3.2簡單的Windows應(yīng)用程序命名規(guī)則作者對“匈牙利”命名規(guī)則做了合理的簡化,下述的命名規(guī)則簡單易用,比較適合于Windows應(yīng)用軟件的開發(fā)。【規(guī)則3-2-1】類名和函數(shù)名用大寫字母開頭的單詞組合而成。例如:classNode;//類名classLeafNode;//類名voidDraw(void);//函數(shù)名voidSetValue(intvalue);//函數(shù)名【規(guī)則3-2-2】變量和參數(shù)用小寫字母開頭的單詞組合而成。例如:BOOLflag;intdrawMode;【規(guī)則3-2-3】常量全用大寫的字母,用下劃線分割單詞。例如:constintMAX=100;constintMAX_LENGTH=100;【規(guī)則3-2-4】靜態(tài)變量加前綴s_(表示static)。例如:voidInit(…){staticints_initValue;//靜態(tài)變量}【規(guī)則3-2-5】如果不得已需要全局變量,則使全局變量加前綴g_(表示global)。例如:intintg_howManyPeople;//全局變量g_howMuchMoney;//全局變量【規(guī)則3-2-6】類的數(shù)據(jù)成員加前綴m_(表示member),這樣可以避免數(shù)據(jù)成員與成員函數(shù)的參數(shù)同名。例如:VoidObject::SetValue(intwidth,intheight){m_width=width;m_height二height;}【規(guī)則3-2-7】為了防止某一軟件庫中的一些標識符和其它軟件庫中的沖突,可以為各種標識符加上能反映軟件性質(zhì)的前綴。例如三維圖形標準OpenGL的所有庫函數(shù)均以gl開頭,所有常量(或宏定義)均以GL開頭。第4章表達式和基本語句表達式和語句都屬于C的短語結(jié)構(gòu)語法。它們看似簡單,但使用時隱患比較多。本章歸納了正確使用表達式和語句的一些規(guī)則與建議。4.1運算符的優(yōu)先級C語言的運算符有數(shù)十個,運算符的優(yōu)先級與結(jié)合律如表4-1所示。注意一元運算符+-*的優(yōu)先級高于對應(yīng)的二元運算符。優(yōu)先級運算符結(jié)合律從高到低排列()[]->.從左至右!++--(類型)sizeof+-*&從右至左*/%從左至右+-從左至右<<>>從左至右〈〈=〉〉=從左至右二二!=從左至右&從左至右從左至右|從左至右&&從左至右||從右至左:從右至左=+=-=*=/=%=&二"二|=<<=>>=從左至右表4-1運算符的優(yōu)先級與結(jié)合律【規(guī)則4-1-1】如果代碼行中的運算符比較多,用括號確定表達式的操作順序,避免使用默認的優(yōu)先級。由于將表4-1熟記是比較困難的,為了防止產(chǎn)生歧義并提高可讀性,應(yīng)當用括號確定表達式的操作順序。例如:word=(high〈〈8)|lowif((a|b)&&(a&c))4.2復(fù)合表達式如a=b=c=0這樣的表達式稱為復(fù)合表達式。允許復(fù)合表達式存在的理由是:(1)書寫簡潔;(2)可以提高編譯效率。但要防止濫用復(fù)合表達式?!疽?guī)則4-2-1】不要編寫太復(fù)雜的復(fù)合表達式。例如:i=a>=b&&c<d&&c+f〈二g+h;//復(fù)合表達式過于復(fù)雜【規(guī)則4-2-2】不要有多用途的復(fù)合表達式。例如:d=(a=b+c)+r;該表達式既求a值又求d值。應(yīng)該拆分為兩個獨立的語句:a=b+c;d=a+r;【規(guī)則4-2-3】不要把程序中的復(fù)合表達式與“真正的數(shù)學(xué)表達式”混淆。例如:if(a〈b〈c)//a〈b〈c是數(shù)學(xué)表達式而不是程序表達式并不表示辻((a〈b)&&(b〈c))而是成了令人費解的辻((a〈b)〈c)4.3if語句if語句是c語言中最簡單、最常用的語句,然而很多程序員用隱含錯誤的方式寫if語句。本節(jié)以“與零值比較”為例,展開討論。4.3.1布爾變量與零值比較【規(guī)則4-3-1】不可將布爾變量直接與TRUE、FALSE或者1、0進行比較。根據(jù)布爾類型的語義,零值為“假”(記為FALSE),任何非零值都是“真”(記為TRUE)。TRUE的值究竟是什么并沒有統(tǒng)一的標準。例如VisualC++將TRUE定義為1,而VisualBasic則將TRUE定義為-1。假設(shè)布爾變量名字為flag,它與零值比較的標準if語句如下:if(flag)//表示flag為真if(!flag)//表示flag為假其它的用法都屬于不良風格,例如:辻(flag==TRUE)if(flag==1)if(flag==FALSE)if(flag==O)4.3.2整型變量與零值比較【規(guī)則4-3-2】應(yīng)當將整型變量用“==”或“!=”直接與0比較。假設(shè)整型變量的名字為value,它與零值比較的標準if語句如下:if(value==0)if(value!=0)不可模仿布爾變量的風格而寫成if(value)//會讓人誤解value是布爾變量if(!value)4.3.3浮點變量與零值比較【規(guī)則4-3-3】不可將浮點變量用“==”或“!=”與任何數(shù)字比較。千萬要留意,無論是float還是double類型的變量,都有精度限制。所以一定要避免將浮點變量用“==”或“!=”與數(shù)字比較,應(yīng)該設(shè)法轉(zhuǎn)化成“〉=”或“〈=”形式。假設(shè)浮點變量的名字為x,應(yīng)當將if(x==0.0)//隱含錯誤的比較轉(zhuǎn)化為辻((x〉=-EPSIN0N)&&(x〈二EPSINON))其中EPSINON是允許的誤差(即精度)。4.3.4指針變量與零值比較【規(guī)則4-3-4】應(yīng)當將指針變量用“==”或“!=”與NULL比較。指針變量的零值是“空”(記為NULL)。盡管NULL的值與0相同,但是兩者意義不同。假設(shè)指針變量的名字為p,它與零值比較的標準if語句如下:if(p==NULL)//p與NULL顯式比較,強調(diào)p是指針變量if(p!=NULL)不要與成if(p==0)//容易讓人誤解p是整型變量if(p!=0)或者//容易讓人誤解p是布爾變量//容易讓人誤解p是布爾變量4.3.5對if語句的補充說明有時候我們可能會看到if(NULL==p)這樣古怪的格式。不是程序?qū)戝e了,是程序員為了防止將if(p==NULL)誤寫成if(p=NULL),而有意把p和NULL顛倒。編譯器認為if(p=NULL)是合法的,但是會指出if(NULL=p)是錯誤的,因為NULL不能被賦值。程序中有時會遇到if/else/return的組合,應(yīng)該將如下不良風格的程序if(condition)returnx;returny;改寫為if(condition){returnx;}else{returny;}或者改寫成更加簡練的return(condition?x:y);4.4循環(huán)語句的效率C循環(huán)語句中,for語句使用頻率最高‘while語句其次,do語句很少用。本節(jié)重點論述循環(huán)體的效率。提高循環(huán)體效率的基本辦法是降低循環(huán)體的復(fù)雜性。【建議4-4-1】在多重循環(huán)中,如果有可能,應(yī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+a[row][col];}}示例4-4(a)低效率:長循環(huán)在最外層for(col=0;col<5;col++){for(row=0;row<100;row++){fum=sum+a[row][col];}}示例4-4(b)高效率:長循環(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次邏輯判斷。并且由于前者老要進行邏輯判斷,打斷了循環(huán)“流水線”作業(yè),使得編譯器不能對循環(huán)進行優(yōu)化處理,降低了效率。如果N非常大,最好采用示例4-4(d)的寫法,可以提高效率。如果N非常小,兩者效率差別并不明顯,采用示例4-4(c)的寫法比較好,因為程序更加簡潔。for(i=0;i<N;i++){if(condition{DoSomething();}else{DoOtherthing();}}表4-4(c)效率低但程序簡潔if(condition){for(i=0;i〈N;i++)DoSomething();}else{for(i=0;i〈N;i++)DoOtherthing();}表4-4(d)效率高但程序不簡潔4?5for語句的循環(huán)控制變量【規(guī)則4-5-1】不可在for循環(huán)體內(nèi)修改循環(huán)變量,防止for循環(huán)失去控制。【建議4-5-1】建議for語句的循環(huán)控制變量的取值采用“半開半閉區(qū)間”寫法。示例4-5(a)中的x值屬于半開半閉區(qū)間“0=〈x〈N”,起點到終點的間隔為N,循環(huán)次數(shù)為N。示例4-5(b)中的x值屬于閉區(qū)間“0=〈x〈=N-1”,起點到終點的間隔為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〈二NT;x++){}示例4-5(b)循環(huán)變量屬于閉區(qū)間4?6switch語句switch是多分支選擇語句,而if語句只有兩個分支可供選擇。雖然可以用嵌套的if語句來實現(xiàn)多分支選擇,但那樣的程序冗長難讀。這是switch語句存在的理由。switch語句的基本格式是:switch(variable){casevaluel:{break;}casevalue2:{break;}default:{break;}}【規(guī)則4-6-1】每個case語句的結(jié)尾不要忘了加break,否則將導(dǎo)致多個分支重疊(除非有意使多個分支重疊)?!疽?guī)則4-6-2】不要忘記最后那個default分支。即使程序真的不需要default處理,也應(yīng)該保留語句default:break;這樣做并非多此一舉,而是為了防止別人誤以為你忘了default處理。4.7goto語句自從提倡結(jié)構(gòu)化設(shè)計以來,goto就成了有爭議的語句。首先,由于goto語句可以靈活跳轉(zhuǎn),如果不加限制,它的確會破壞結(jié)構(gòu)化設(shè)計風格。其次,goto語句經(jīng)常帶來錯誤或隱患。它可能跳過了某些對象的構(gòu)造、變量的初始化、重要的計算等語句,例如:gotostate;Strings1,s2;//被goto跳過intsum=0;//被goto跳過state:如果編譯器不能發(fā)覺此類錯誤,每用一次got。語句都可能留下隱患。很多人建議廢除C的got。語句,以絕后患。但實事求是地說,錯誤是程序員自己造成的,不是goto的過錯。goto語句至少有一處可顯神通,它能從多重循環(huán)體中咻地一下子跳到外面,用不著寫很多次的break語句;例如{…{…{…gotoerror;}}}error:就象樓房著火了,來不及從樓梯一級一級往下走,可從窗口跳出火坑。所以我們主張少用、慎用goto語句,而不是禁用。第5章常量常量是一種標識符,它的值在運行期間恒定不變。C語言用#define來定義常量(稱為宏常量)。C++語言除了#define外還可以用const來定義常量(稱為const常量)。5?1為什么需要常量如果不使用常量,直接在程序中填寫數(shù)字或字符串,將會有什么麻煩?(1)程序的可讀性(可理解性)變差。程序員自己會忘記那些數(shù)字或字符串是什么意思,用戶則更加不知它們從何處來、表示什么。(2)在程序的很多地方輸入同樣的數(shù)字或字符串,難保不發(fā)生書寫錯誤。(3)如果要修改數(shù)字或字符串,則會在很多地方改動,既麻煩又容易出錯?!疽?guī)則5-1-1]盡量使用含義直觀的常量來表示那些將在程序中多次出現(xiàn)的數(shù)字或字符串。例如:#defineMAX100/*C語言的宏常量*/constintMAX=100;//C++語言的const常量constfloatPI=3.14159;//C++語言的const常量5?2const與#define的比較C++語言可以用const來定義常量,也可以用#define來定義常量。但是前者比后者有更多的優(yōu)占.八、、?const常量有數(shù)據(jù)類型,而宏常量沒有數(shù)據(jù)類型。編譯器可以對前者進行類型安全檢查。而對后者只進行字符替換,沒有類型安全檢查,并且在字符替換可能會產(chǎn)生意料不到的錯誤(邊際效應(yīng))。有些集成化的調(diào)試工具可以對const常量進行調(diào)試,但是不能對宏常量進行調(diào)試?!疽?guī)則5-2-1】在C++程序中只使用const常量而不使用宏常量,即const常量完全取代宏常量。5.3常量定義規(guī)則【規(guī)則5-3-1]需要對外公開的常量放在頭文件中,不需要對外公開的常量放在定義文件的頭部。為便于管理,可以把不同模塊的常量集中存放在一個公共的頭文件中?!疽?guī)則5-3-2]如果某一常量與其它常量密切相關(guān),應(yīng)在定義中包含這種關(guān)系,而不應(yīng)給出一些孤立的值。例如:constfloatRADIUS=100;constfloatDIAMETER=RADIUS*2;第6章函數(shù)設(shè)計函數(shù)是c程序的基本功能單元,其重要性不言而喻。函數(shù)設(shè)計的細微缺點很容易導(dǎo)致該函數(shù)被錯用,所以光使函數(shù)的功能正確是不夠的。本章重點論述函數(shù)的接口設(shè)計和內(nèi)部實現(xiàn)的一些規(guī)則。函數(shù)接口的兩個要素是參數(shù)和返回值。c語言中,函數(shù)的參數(shù)和返回值的傳遞方式有兩種:值傳遞(passbyvalue)和指針傳遞(passbypointer)。C++語言中多了引用傳遞(passbyreference)。由于引用傳遞的性質(zhì)象指針傳遞,而使用方式卻象值傳遞,初學(xué)者常常迷惑不解,容易引起混亂,請先閱讀6.6節(jié)“引用與指針的比較”。6.1參數(shù)的規(guī)則【規(guī)則6-1-1]參數(shù)的書寫要完整,不要貪圖省事只寫參數(shù)的類型而省略參數(shù)名字。如果函數(shù)沒有參數(shù),則用void填充。例如:voidSetValue(intwidth,intheight);//良好的風格voidSetValue(int,int);//不良的風格floatGetValue(void);//良好的風格floatGetValue();//不良的風格【規(guī)則6-1-2】參數(shù)命名要恰當,順序要合理。例如編寫字符串拷貝函數(shù)StringCopy,它有兩個參數(shù)。如果把參數(shù)名字起為strl和str2,例如voidStringCopy(char*str1,char*str2);那么我們很難搞清楚究竟是把str1拷貝到str2中,還是剛好倒過來??梢园褏?shù)名字起得更有意義,如叫strSource和strDestination。這樣從名字上就可以看出應(yīng)該把strSource拷貝到strDestination。還有一個問題,這兩個參數(shù)那一個該在前那一個該在后?參數(shù)的順序要遵循程序員的習慣。一般地,應(yīng)將目的參數(shù)放在前面,源參數(shù)放在后面。如果將函數(shù)聲明為:voidStringCopy(char*strSource,char*strDestination);別人在使用時可能會不假思索地寫成如下形式:charstr[20];StringCopy(str,“HelloWorld”);//參數(shù)順序顛倒【規(guī)則6-1-3]如果參數(shù)是指針,且僅作輸入用,則應(yīng)在類型前加const,以防止該指針在函數(shù)體內(nèi)被意外修改。例如:voidStringCopy(char*strDestination,constchar*strSource);【規(guī)貝96-1-4]如果輸入?yún)?shù)以值傳遞的方式傳遞對象,貝9宜改用“const&”方式來傳遞,這樣可以省去臨時對象的構(gòu)造和析構(gòu)過程,從而提高效率。【建議6-1-1]避免函數(shù)有太多的參數(shù),參數(shù)個數(shù)盡量控制在5個以內(nèi)。如果參數(shù)太多,在使用時容易將參數(shù)類型或順序搞錯?!窘ㄗh6-1-2]盡量不要使用類型和數(shù)目不確定的參數(shù)。C標準庫函數(shù)printf是采用不確定參數(shù)的典型代表,其原型為:intprintf(constchat*format[,argument]…);這種風格的函數(shù)在編譯時喪失了嚴格的類型安全檢查。6.2返回值的規(guī)則【規(guī)則6-2-1]不要省略返回值的類型。C語言中,凡不加類型說明的函數(shù),一律自動按整型處理。這樣做不會有什么好處,卻容易被誤解為void類型。C++語言有很嚴格的類型安全檢查,不允許上述情況
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 附件:1.1521項擬繼續(xù)有效行業(yè)標準復(fù)審結(jié)論-表(征求意見稿)
- 石河子大學(xué)《藥物波譜解析》2022-2023學(xué)年第一學(xué)期期末試卷
- 石河子大學(xué)《食品包裝學(xué)》2022-2023學(xué)年第一學(xué)期期末試卷
- 石河子大學(xué)《計算機網(wǎng)絡(luò)基礎(chǔ)》2022-2023學(xué)年期末試卷
- 沈陽理工大學(xué)《弱信號檢測技術(shù)》2021-2022學(xué)年第一學(xué)期期末試卷
- 沈陽理工大學(xué)《建筑節(jié)能》2023-2024學(xué)年第一學(xué)期期末試卷
- 沈陽理工大學(xué)《過程控制系統(tǒng)與儀表》2021-2022學(xué)年期末試卷
- 沈陽理工大學(xué)《電鍍工藝》2022-2023學(xué)年期末試卷
- 沈陽理工大學(xué)《環(huán)境工程概論》2023-2024學(xué)年第一學(xué)期期末試卷
- 合同產(chǎn)值申報
- 建筑工程項目管理咨詢招標(范本)
- 三位數(shù)除兩位數(shù)的除法練習題
- 慢性胃炎的中醫(yī)治療培訓(xùn)課件
- Python程序設(shè)計課件第7章面向?qū)ο蟪绦蛟O(shè)計
- 最新爆破安全規(guī)程
- 主題班會課防盜
- 幼兒園課件《撓撓小怪物》
- 教師教案檢查八大評分標準教案的評分標準
- 政府會計基礎(chǔ)知識講義
- 幼兒園整合式主題活動設(shè)計案例《溫馨家園》
- 荒漠區(qū)生態(tài)治理(麥草沙障、植物固沙)施工方案
評論
0/150
提交評論