久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

C++編程修養(yǎng)

 accesine 2005-10-12

編程修養(yǎng)(一)

什么是好的程序員,?是不是懂得很多技術(shù)細(xì)節(jié),?還是懂底層編程,?還是編程速度比較快?我覺(jué)得都不是,。對(duì)于一些技術(shù)細(xì)節(jié)來(lái)說(shuō)和底層的技術(shù),,只要看幫助,查資料就能找到,,對(duì)于速度快,,只要編得多也就熟能生巧了。

我認(rèn)為好的程序員應(yīng)該有以下幾方面的素質(zhì):

1
,、有專研精神,,勤學(xué)善問(wèn)、舉一反三。
2
,、積極向上的態(tài)度,,有創(chuàng)造性思維。

3
,、與人積極交流溝通的能力,,有團(tuán)隊(duì)精神。

4
,、謙虛謹(jǐn)慎,,戒驕戒燥。

5
,、寫出的代碼質(zhì)量高,。包括:代碼的穩(wěn)定、易讀,、規(guī)范,、易維護(hù)、專業(yè),。


這些都是程序員的修養(yǎng),,這里我想談?wù)?/SPAN>編程修養(yǎng),也就是上述中的第5點(diǎn),。我覺(jué)得,,如果我要了解一個(gè)作者,我會(huì)看他所寫的小說(shuō),,如果我要了解一個(gè)畫家,,我會(huì)看他所畫的圖畫,如果我要了解一個(gè)工人,,我會(huì)看他所做出來(lái)的產(chǎn)品,,同樣,如果我要了解一個(gè)程序員,,我想首先我最想看的就是他的程序代碼,,程序代碼可以看出一個(gè)程序員的素質(zhì)和修養(yǎng),程序就像一個(gè)作品,,有素質(zhì)有修養(yǎng)的程序員的作品必然是一圖精美的圖畫,,一首美妙的歌曲,一本賞心悅目的小說(shuō),。

我看過(guò)許多程序,,沒(méi)有注釋,沒(méi)有縮進(jìn),,胡亂命名的變量名,,等等,等等,我把這種人統(tǒng)稱為沒(méi)有修養(yǎng)的程序,,這種程序員,,是在做創(chuàng)造性的工作嗎?不,,完全就是在搞破壞,,他們與其說(shuō)是在編程,還不如說(shuō)是在對(duì)源程序進(jìn)行加密,,這種程序員,,見一個(gè)就應(yīng)該開除一個(gè),因?yàn)樗幍某绦蛩鶆?chuàng)造的價(jià)值,,遠(yuǎn)遠(yuǎn)小于需要在上面進(jìn)行維護(hù)的價(jià)值,。

程序員應(yīng)該有程序員的修養(yǎng),那怕再累,,再?zèng)]時(shí)間,,也要對(duì)自己的程序負(fù)責(zé)。我寧可要那種動(dòng)作慢,,技術(shù)一般,,但有良好的寫程序風(fēng)格的程序員,也不要那種技術(shù)強(qiáng),、動(dòng)作快的搞破壞的程序員,。有句話叫字如其人,我想從程序上也能看出一個(gè)程序員的優(yōu)劣,。因?yàn)?,程序是程序員的作品,作品的好壞直截關(guān)系到程序員的聲譽(yù)和素質(zhì),。而修養(yǎng)好的程序員一定能做出好的程序和軟件,。

有個(gè)成語(yǔ)叫獨(dú)具匠心,意思是做什么都要做得很專業(yè),,很用心,,如果你要做一個(gè),也就是造詣高深的人,,那么,,從一件很簡(jiǎn)單的作品上就能看出你有沒(méi)有的特性,我覺(jué)得做一個(gè)程序員不難,,但要做一個(gè)程序匠就不簡(jiǎn)單了。編程序很簡(jiǎn)單,,但編出有質(zhì)量的程序就難了,。

我在這里不討論過(guò)深的技術(shù),我只想在一些容易讓人忽略的東西上說(shuō)一說(shuō),雖然這些東西可能很細(xì)微,,但如果你不注意這些細(xì)微之處的話,,那么他將會(huì)極大的影響你的整個(gè)軟件質(zhì)量,以及整個(gè)軟件程的實(shí)施,,所謂千里之堤,,毀于蟻穴

細(xì)微之處見真功,,真正能體現(xiàn)一個(gè)程序的功底恰恰在這些細(xì)微之處,。

這就是程序員的——編程修養(yǎng)。我總結(jié)了在用C/C++語(yǔ)言(主要是C語(yǔ)言)進(jìn)行程序?qū)懽魃系娜€(gè)修養(yǎng),,通過(guò)這些,,你可以寫出質(zhì)量高的程序,同時(shí)也會(huì)讓看你程序的人漬漬稱道,,那些看過(guò)你程序的人一定會(huì)說(shuō):這個(gè)人的編程修養(yǎng)不錯(cuò)

————————————————————————

01
、版權(quán)和版本
02
,、縮進(jìn),、空格、換行,、空行,、對(duì)齊
03
、程序注釋
04
,、函數(shù)的[in][out]參數(shù)
05
,、對(duì)系統(tǒng)調(diào)用的返回進(jìn)行判斷
06
if 語(yǔ)句對(duì)出錯(cuò)的處理
07
,、頭文件中的#ifndef
08
,、在堆上分配內(nèi)存
09
、變量的初始化
10
,、hc文件的使用
11
,、出錯(cuò)信息的處理
12
、常用函數(shù)和循環(huán)語(yǔ)句中的被計(jì)算量
13
,、函數(shù)名和變量名的命名
14
,、函數(shù)的傳值和傳指針
15
、修改別人程序的修養(yǎng)
16
,、把相同或近乎相同的代碼形成函數(shù)和宏
17
,、表達(dá)式中的括號(hào)
18
、函數(shù)參數(shù)中的const
19
,、函數(shù)的參數(shù)個(gè)數(shù)
20
,、函數(shù)的返回類型,,不要省略
21
goto語(yǔ)句的使用
22
,、宏的使用
23
,、static的使用
24
、函數(shù)中的代碼尺寸
25
,、typedef的使用
26
,、為常量聲明宏
27
、不要為宏定義加分號(hào)
28
,、||&&的語(yǔ)句執(zhí)行順序
29
,、盡量用for而不是while做循環(huán)
30
、請(qǐng)sizeof類型而不是變量
31
,、不要忽略Warning
32
,、書寫Debug版和Release版的程序



1
、版權(quán)和版本
———————
好的程序員會(huì)給自己的每個(gè)函數(shù),,每個(gè)文件,,都注上版權(quán)和版本。

對(duì)于C/C++的文件,,文件頭應(yīng)該有類似這樣的注釋:
/************************************************************************
*
*
文件名:network.c
*
*
文件描述:網(wǎng)絡(luò)通訊函數(shù)集
*
*
創(chuàng)建人: Hao Chen, 200323
*
*
版本號(hào):1.0
*
*
修改記錄:
*
************************************************************************/

而對(duì)于函數(shù)來(lái)說(shuō),,應(yīng)該也有類似于這樣的注釋:

/*================================================================
*
*
數(shù) 名:XXX
*
*
數(shù):
*
* type name [IN] : descripts
*
*
功能描述:
*
* ..............
*
*
值:成功TRUE,失敗FALSE
*
*
拋出異常:
*
*
者:ChenHao 2003/4/2
*
================================================================*/

這樣的描述可以讓人對(duì)一個(gè)函數(shù),,一個(gè)文件有一個(gè)總體的認(rèn)識(shí),,對(duì)代碼的易讀性和易維護(hù)性有很大的好處。這是好的作品產(chǎn)生的開始,。


2
,、縮進(jìn)、空格,、換行,、空行、對(duì)齊
————————————————
i)
縮進(jìn)應(yīng)該是每個(gè)程序都會(huì)做的,,只要學(xué)程序過(guò)程序就應(yīng)該知道這個(gè),,但是我仍然看過(guò)不縮進(jìn)的程序,或是亂縮進(jìn)的程序,,如果你的公司還有寫程序不縮進(jìn)的程序員,,請(qǐng)毫不猶豫的開除他吧,并以破壞源碼罪起訴他,,還要他賠償讀過(guò)他程序的人的精神損失費(fèi),。縮進(jìn),,這是不成文規(guī)矩,,我再重提一下吧,,一個(gè)縮進(jìn)一般是一個(gè)TAB鍵或是4個(gè)空格,。(最好用TAB鍵)

ii)
空格,。空格能給程序代來(lái)什么損失嗎,?沒(méi)有,,有效的利用空格可以讓你的程序讀進(jìn)來(lái)更加賞心悅目。而不一堆表達(dá)式擠在一起,??纯聪旅娴拇a:

ha=(ha*128+*key++)%tabPtr->size;

ha = ( ha * 128 + *key++ ) % tabPtr->size;

有空格和沒(méi)有空格的感覺(jué)不一樣吧。一般來(lái)說(shuō),,語(yǔ)句中要在各個(gè)操作符間加空格,,函數(shù)調(diào)用時(shí),要以各個(gè)參數(shù)間加空格,。如下面這種加空格的和不加的:

if ((hProc=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid))==NULL){
}

if ( ( hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid) ) == NULL ){
}

iii)
換行,。不要把語(yǔ)句都寫在一行上,這樣很不好,。如:

for(i=0;i‘9‘)&&(a[i]<‘a(chǎn)‘||a[i]>‘z‘)) break;

我拷,,這種即無(wú)空格,又無(wú)換行的程序在寫什么???加上空格和換行吧。

for ( i=0; i if ( ( a[i] < ‘0‘ || a[i] > ‘9‘ ) &&
( a[i] < ‘a(chǎn)‘ || a[i] > ‘z‘ ) ) {
break;
}
}

好多了吧,?有時(shí)候,,函數(shù)參數(shù)多的時(shí)候,最好也換行,,如:

CreateProcess(
NULL,
cmdbuf,
NULL,
NULL,
bInhH,
dwCrtFlags,
envbuf,
NULL,
&siStartInfo,
&prInfo
);

條件語(yǔ)句也應(yīng)該在必要時(shí)換行:

if ( ch >= ‘0‘ || ch <= ‘9‘ ||
ch >= ‘a(chǎn)‘ || ch <= ‘z‘ ||
ch >= ‘A‘ || ch <= ‘Z‘ )


iv)
空行,。不要不加空行,空行可以區(qū)分不同的程序塊,,程序塊間,,最好加上空行。如:

HANDLE hProcess;
PROCESS_T procInfo;

/* open the process handle */
if((hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid)) == NULL)
{
return LSE_MISC_SYS;
}

memset(&procInfo, 0, sizeof(procInfo));
procInfo.idProc = pid;
procInfo.hdProc = hProcess;
procInfo.misc |= MSCAVA_PROC;

return(0);

v)
對(duì)齊,。用TAB鍵對(duì)齊你的一些變量的聲明或注釋,,一樣會(huì)讓你的程序好看一些。如:

typedef struct _pt_man_t_ {
int numProc; /* Number of processes */
int maxProc; /* Max Number of processes */
int numEvnt; /* Number of events */
int maxEvnt; /* Max Number of events */
HANDLE* pHndEvnt; /* Array of events */
DWORD timeout; /* Time out interval */
HANDLE hPipe; /* Namedpipe */
TCHAR usr[MAXUSR];/* User name of the process */
int numMsg; /* Number of Message */
int Msg[MAXMSG];/* Space for intro process communicate */
} PT_MAN_T;

怎么樣,?感覺(jué)不錯(cuò)吧,。

這里主要講述了如果寫出讓人賞心悅目的代碼,好看的代碼會(huì)讓人的心情愉快,,讀起代碼也就不累,,工整,、整潔的程序代碼,通常更讓人歡迎,,也更讓人稱道?,F(xiàn)在的硬盤空間這么大,不要讓你的代碼擠在一起,,這樣它們會(huì)抱怨你虐待它們的,。好了,用縮進(jìn),、空格,、換行、空行,、對(duì)齊裝飾你的代碼吧,,讓他們從沒(méi)有秩序的土匪中變成一排排整齊有秩序的正規(guī)部隊(duì)吧。


3
,、程序注釋
——————
養(yǎng)成寫程序注釋的習(xí)慣,,這是每個(gè)程序員所必須要做的工作。我看過(guò)那種幾千行,,卻居然沒(méi)有一行注釋的程序,。這就如同在公路上駕車卻沒(méi)有路標(biāo)一樣。用不了多久,,連自己都不知道自己的意圖了,,還要花上幾倍的時(shí)間才看明白,這種浪費(fèi)別人和自己的時(shí)間的人,,是最為可恥的人,。

是的,你也許會(huì)說(shuō),,你會(huì)寫注釋,,真的嗎?注釋的書寫也能看出一個(gè)程序員的功底,。一般來(lái)說(shuō)你需要至少寫這些地方的注釋:文件的注釋,、函數(shù)的注釋、變量的注釋,、算法的注釋,、功能塊的程序注釋。主要就是記錄你這段程序是干什么的,?你的意圖是什么,?你這個(gè)變量是用來(lái)做什么的?等等,。

不要以為注釋好寫,,有一些算法是很難說(shuō)或?qū)懗鰜?lái)的,,只能意會(huì),我承認(rèn)有這種情況的時(shí)候,,但你也要寫出來(lái),,正好可以訓(xùn)練一下自己的表達(dá)能力。而表達(dá)能力正是那種悶頭搞技術(shù)的技術(shù)人員最缺的,,你有再高的技術(shù),,如果你表達(dá)能力不行,,你的技術(shù)將不能得到充分的發(fā)揮,。因?yàn)椋@是一個(gè)團(tuán)隊(duì)的時(shí)代,。

好了,,說(shuō)幾個(gè)注釋的技術(shù)細(xì)節(jié):

i)
對(duì)于行注釋(“//”)比塊注釋(“/* */”)要好的說(shuō)法,我并不是很同意,。因?yàn)橐恍├习姹镜?/SPAN>C編譯器并不支持行注釋,,所以為了你的程序的移植性,請(qǐng)你還是盡量使用塊注釋,。

ii)
你也許會(huì)為塊注釋的不能嵌套而不爽,,那么你可以用預(yù)編譯來(lái)完成這個(gè)功能。使用“#if 0”“#endif”括起來(lái)的代碼,,將不被編譯,,而且還可以嵌套。


4
,、函數(shù)的[in][out]參數(shù)
———————————

我經(jīng)??吹竭@樣的程序:
FuncName(char* str)
{
int len = strlen(str);
.....
}

char*
GetUserName(struct user* pUser)
{
return pUser->name;
}

不!請(qǐng)不要這樣做,。

你應(yīng)該先判斷一下傳進(jìn)來(lái)的那個(gè)指針是不是為空,。如果傳進(jìn)來(lái)的指針為空的話,那么,,你的一個(gè)大的系統(tǒng)就會(huì)因?yàn)檫@一個(gè)小的函數(shù)而崩潰,。一種更好的技術(shù)是使用斷言(assert),這里我就不多說(shuō)這些技術(shù)細(xì)節(jié)了,。當(dāng)然,,如果是在C++中,引用要比指針好得多,,但你也需要對(duì)各個(gè)參數(shù)進(jìn)行檢查,。

寫有參數(shù)的函數(shù)時(shí),首要工作,,就是要對(duì)傳進(jìn)來(lái)的所有參數(shù)進(jìn)行合法性檢查,。而對(duì)于傳出的參數(shù)也應(yīng)該進(jìn)行檢查,,這個(gè)動(dòng)作當(dāng)然應(yīng)該在函數(shù)的外部,也就是說(shuō),,調(diào)用完一個(gè)函數(shù)后,,應(yīng)該對(duì)其傳出的值進(jìn)行檢查。

當(dāng)然,,檢查會(huì)浪費(fèi)一點(diǎn)時(shí)間,,但為了整個(gè)系統(tǒng)不至于出現(xiàn)非法操作或是“Core Dump”的系統(tǒng)級(jí)的錯(cuò)誤,多花這點(diǎn)時(shí)間還是很值得的,。


5
,、對(duì)系統(tǒng)調(diào)用的返回進(jìn)行判斷
——————————————
繼續(xù)上一條,對(duì)于一些系統(tǒng)調(diào)用,,比如打開文件,,我經(jīng)常看到,,許多程序員對(duì)fopen返回的指針不做任何判斷,,就直接使用了。然后發(fā)現(xiàn)文件的內(nèi)容怎么也讀出不,,或是怎么也寫不進(jìn)去,。還是判斷一下吧:

fp = fopen("log.txt", "a");
if ( fp == NULL ){
printf("Error: open file error\n");
return FALSE;
}

其它還有許多啦,比如:socket返回的socket號(hào),,malloc返回的內(nèi)存,。請(qǐng)對(duì)這些系統(tǒng)調(diào)用返回的東西進(jìn)行判斷。
 
6
,、if 語(yǔ)句對(duì)出錯(cuò)的處理
———————————
我看見你說(shuō)了,,這有什么好說(shuō)的。還是先看一段程序代碼吧,。
if ( ch >= ‘0‘ && ch <= ‘9‘ ){
/*
正常處理代碼 */
}else{
/*
輸出錯(cuò)誤信息 */
printf("error ......\n");
return ( FALSE );
}

這種結(jié)構(gòu)很不好,,特別是如果正常處理代碼很長(zhǎng)時(shí),對(duì)于這種情況,,最好不要用else,。先判斷錯(cuò)誤,如:

if ( ch < ‘0‘ || ch > ‘9‘ ){
/*
輸出錯(cuò)誤信息 */
printf("error ......\n");
return ( FALSE );
}

/*
正常處理代碼 */
......


這樣的結(jié)構(gòu),,不是很清楚嗎,?突出了錯(cuò)誤的條件,讓別人在使用你的函數(shù)的時(shí)候,,第一眼就能看到不合法的條件,,于是就會(huì)更下意識(shí)的避免。


7
、頭文件中的#ifndef
——————————
千萬(wàn)不要忽略了頭件的中的#ifndef,,這是一個(gè)很關(guān)鍵的東西,。比如你有兩個(gè)C文件,這兩個(gè)C文件都include了同一個(gè)頭文件,。而編譯時(shí),,這兩個(gè)C文件要一同編譯成一個(gè)可運(yùn)行文件,于是問(wèn)題來(lái)了,,大量的聲明沖突,。

還是把頭文件的內(nèi)容都放在#ifndef#endif中吧。不管你的頭文件會(huì)不會(huì)被多個(gè)文件引用,,你都要加上這個(gè),。一般格式是這樣的:

#ifndef <
標(biāo)識(shí)>
#define <
標(biāo)識(shí)>

......
......

#endif

<
標(biāo)識(shí)>在理論上來(lái)說(shuō)可以是自由命名的,但每個(gè)頭文件的這個(gè)標(biāo)識(shí)都應(yīng)該是唯一的,。標(biāo)識(shí)的命名規(guī)則一般是頭文件名全大寫,,前后加下劃線,并把文件名中的“.”也變成下劃線,,如:stdio.h

#ifndef _STDIO_H_
#define _STDIO_H_

......

#endif

BTW:預(yù)編譯有多很有用的功能。你會(huì)用預(yù)編譯嗎,?)


8
,、在堆上分配內(nèi)存
—————————
可能許多人對(duì)內(nèi)存分配上的 stack” heap”還不是很明白。包括一些科班出身的人也不明白這兩個(gè)概念,。我不想過(guò)多的說(shuō)這兩個(gè)東西,。簡(jiǎn)單的來(lái)講,stack上分配的內(nèi)存系統(tǒng)自動(dòng)釋放,,heap上分配的內(nèi)存,,系統(tǒng)不釋放,哪怕程序退出,,那一塊內(nèi)存還是在那里,。stack一般是靜態(tài)分配內(nèi)存,heap上一般是動(dòng)態(tài)分配內(nèi)存,。

malloc系統(tǒng)函數(shù)分配的內(nèi)存就是從堆上分配內(nèi)存,。從堆上分配的內(nèi)存一定要自己釋放。用free釋放,,不然就是術(shù)語(yǔ)——“內(nèi)存泄露(或是內(nèi)存漏洞—— Memory Leak,。于是,系統(tǒng)的可分配內(nèi)存會(huì)隨malloc越來(lái)越少,,直到系統(tǒng)崩潰,。還是來(lái)看看棧內(nèi)存堆內(nèi)存的差別吧。

棧內(nèi)存分配
—————
char*
AllocStrFromStack()
{
char pstr[100];
return pstr;
}


堆內(nèi)存分配
—————
char*
AllocStrFromHeap(int len)
{
char *pstr;

if ( len <= 0 ) return NULL;
return ( char* ) malloc( len );
}

對(duì)于第一個(gè)函數(shù),那塊pstr的內(nèi)存在函數(shù)返回時(shí)就被系統(tǒng)釋放了,。于是所返回的char*什么也沒(méi)有,。而對(duì)于第二個(gè)函數(shù),是從堆上分配內(nèi)存,,所以哪怕是程序退出時(shí),,也不釋放,所以第二個(gè)函數(shù)的返回的內(nèi)存沒(méi)有問(wèn)題,,可以被使用,。但一定要調(diào)用free釋放,不然就是Memory Leak,!

在堆上分配內(nèi)存很容易造成內(nèi)存泄漏,,這是C/C++的最大的克星,如果你的程序要穩(wěn)定,,那么就不要出現(xiàn)Memory Leak,。所以,我還是要在這里千叮嚀萬(wàn)囑付,,在使用malloc系統(tǒng)函數(shù)(包括calloc,,realloc)時(shí)千萬(wàn)要小心。

記得有一個(gè)UNIX上的服務(wù)應(yīng)用程序,,大約有幾百的C文件編譯而成,,運(yùn)行測(cè)試良好,等使用時(shí),,每隔三個(gè)月系統(tǒng)就是down一次,,搞得許多人焦頭爛額,查不出問(wèn)題所在,。只好,,每隔兩個(gè)月人工手動(dòng)重啟系統(tǒng)一次。出現(xiàn)這種問(wèn)題就是Memery Leak在做怪了,,在C/C++中這種問(wèn)題總是會(huì)發(fā)生,,所以你一定要小心。一個(gè)Rational的檢測(cè)工作——Purify,,可以幫你測(cè)試你的程序有沒(méi)有內(nèi)存泄漏,。

我保證,做過(guò)許多C/C++的工程的程序員,,都會(huì)對(duì)malloc或是new有些感冒,。當(dāng)你什么時(shí)候在使用mallocnew時(shí),有一種輕度的緊張和惶恐的感覺(jué)時(shí),,你就具備了這方面的修養(yǎng)了,。

對(duì)于mallocfree的操作有以下規(guī)則:

1)
配對(duì)使用,,有一個(gè)malloc,就應(yīng)該有一個(gè)free,。(C++中對(duì)應(yīng)為newdelete
2)
盡量在同一層上使用,,不要像上面那種,malloc在函數(shù)中,,而free在函數(shù)外,。最好在同一調(diào)用層上使用這兩個(gè)函數(shù)。
3) malloc
分配的內(nèi)存一定要初始化,。free后的指針一定要設(shè)置為NULL,。

注:雖然現(xiàn)在的操作系統(tǒng)(如:UNIXWin2k/NT)都有進(jìn)程內(nèi)存跟蹤機(jī)制,也就是如果你有沒(méi)有釋放的內(nèi)存,,操作系統(tǒng)會(huì)幫你釋放,。但操作系統(tǒng)依然不會(huì)釋放你程序中所有產(chǎn)生了Memory Leak的內(nèi)存,所以,,最好還是你自己來(lái)做這個(gè)工作,。(有的時(shí)候不知不覺(jué)就出現(xiàn)Memory Leak了,而且在幾百萬(wàn)行的代碼中找無(wú)異于海底撈針,,Rational有一個(gè)工具叫Purify,,可能很好的幫你檢查程序中的Memory Leak


9
、變量的初始化
————————
接上一條,,變量一定要被初始化再使用,。C/C++編譯器在這個(gè)方面不會(huì)像JAVA一樣幫你初始化,這一切都需要你自己來(lái),,如果你使用了沒(méi)有初始化的變量,結(jié)果未知,。好的程序員從來(lái)都會(huì)在使用變量前初始化變量的,。如:

1)
對(duì)malloc分配的內(nèi)存進(jìn)行memset清零操作。(可以使用calloc分配一塊全零的內(nèi)存)
2)
對(duì)一些棧上分配的struct或數(shù)組進(jìn)行初始化,。(最好也是清零)

不過(guò)話又說(shuō)回來(lái)了,,初始化也會(huì)造成系統(tǒng)運(yùn)行時(shí)間有一定的開銷,所以,,也不要對(duì)所有的變量做初始化,,這個(gè)也沒(méi)有意義。好的程序員知道哪些變量需要初始化,,哪些則不需要,。如:以下這種情況,則不需要,。

char *pstr; /*
一個(gè)字符串 */
pstr = ( char* ) malloc( 50 );
if ( pstr == NULL ) exit(0);
strcpy( pstr, "Hello Wrold" );

但如果是下面一種情況,,最好進(jìn)行內(nèi)存初始化。(指針是一個(gè)危險(xiǎn)的東西,一定要初始化)

char **pstr; /*
一個(gè)字符串?dāng)?shù)組 */
pstr = ( char** ) malloc( 50 );
if ( pstr == NULL ) exit(0);

/*
讓數(shù)組中的指針都指向NULL */
memset( pstr, 0, 50*sizeof(char*) );

而對(duì)于全局變量,,和靜態(tài)變量,,一定要聲明時(shí)就初始化。因?yàn)槟悴恢浪谝淮螘?huì)在哪里被使用,。所以使用前初始這些變量是比較不現(xiàn)實(shí)的,,一定要在聲明時(shí)就初始化它們。如:

Links *plnk = NULL; /*
對(duì)于全局變量plnk初始化為NULL */


10
,、hc文件的使用
—————————
H
文件和C文件怎么用呢,?一般來(lái)說(shuō),H文件中是declare(聲明),,C文件中是define(定義),。因?yàn)?/SPAN>C文件要編譯成庫(kù)文件(Windows下是.obj/.libUNIX下是.o/.a),,如果別人要使用你的函數(shù),,那么就要引用你的H文件,所以,,H文件中一般是變量,、宏定義、枚舉,、結(jié)構(gòu)和函數(shù)接口的聲明,,就像一個(gè)接口說(shuō)明文件一樣。而C文件則是實(shí)現(xiàn)細(xì)節(jié),。

H
文件和C文件最大的用處就是聲明和實(shí)現(xiàn)分開,。這個(gè)特性應(yīng)該是公認(rèn)的了,但我仍然看到有些人喜歡把函數(shù)寫在H文件中,,這種習(xí)慣很不好,。(如果是C++話,對(duì)于其模板函數(shù),,在VC中只有把實(shí)現(xiàn)和聲明都寫在一個(gè)文件中,,因?yàn)?/SPAN>VC不支持export關(guān)鍵字)。而且,,如果在H文件中寫上函數(shù)的實(shí)現(xiàn),,你還得在makefile中把頭文件的依賴關(guān)系也加上去,這個(gè)就會(huì)讓你的makefile很不規(guī)范,。

最后,,有一個(gè)最需要注意的地方就是:帶初始化的全局變量不要放在H文件中!

例如有一個(gè)處理錯(cuò)誤信息的結(jié)構(gòu):

char* errmsg[] = {
/* 0 */ "No error",
/* 1 */ "Open file error",
/* 2 */ "Failed in sending/receiving a message",
/* 3 */ "Bad arguments",
/* 4 */ "Memeroy is not enough",
/* 5 */ "Service is down; try later",
/* 6 */ "Unknow information",
/* 7 */ "A socket operation has failed",
/* 8 */ "Permission denied",
/* 9 */ "Bad configuration file format",
/* 10 */ "Communication time out",
......
......
};

請(qǐng)不要把這個(gè)東西放在頭文件中,,因?yàn)槿绻愕倪@個(gè)頭文件被5個(gè)函數(shù)庫(kù)(.lib或是.a)所用到,,于是他就被鏈接在這5個(gè).lib.a中,,而如果你的一個(gè)程序用到了這5個(gè)函數(shù)庫(kù)中的函數(shù),并且這些函數(shù)都用到了這個(gè)出錯(cuò)信息數(shù)組,。那么這份信息將有5個(gè)副本存在于你的執(zhí)行文件中,。如果你的這個(gè)errmsg很大的話,而且你用到的函數(shù)庫(kù)更多的話,,你的執(zhí)行文件也會(huì)變得很大,。

正確的寫法應(yīng)該把它寫到C文件中,然后在各個(gè)需要用到errmsgC文件頭上加上 extern char* errmsg[]; 的外部聲明,,讓編譯器在鏈接時(shí)才去管他,,這樣一來(lái),就只會(huì)有一個(gè)errmsg存在于執(zhí)行文件中,,而且,,這樣做很利于封裝。

我曾遇到過(guò)的最瘋狂的事,,就是在我的目標(biāo)文件中,,這個(gè)errmsg一共有112個(gè)副本,執(zhí)行文件有8M左右,。當(dāng)我把errmsg放到C文件中,,并為一千多個(gè)C文件加上了extern的聲明后,所有的函數(shù)庫(kù)文件尺寸都下降了20%左右,,而我的執(zhí)行文件只有5M了,。一下子少了3M啊。

備注
—————
有朋友對(duì)我說(shuō),,這個(gè)只是一個(gè)特例,,因?yàn)椋绻?/SPAN>errmsg在執(zhí)行文件中存在多個(gè)副本時(shí),,可以加快程序運(yùn)行速度,,理由是errmsg的多個(gè)復(fù)本會(huì)讓系統(tǒng)的內(nèi)存換頁(yè)降低,達(dá)到效率提升,。像我們這里所說(shuō)的errmsg只有一份,當(dāng)某函數(shù)要用errmsg時(shí),,如果內(nèi)存隔得比較遠(yuǎn),,會(huì)產(chǎn)生換頁(yè),反而效率不高,。

這個(gè)說(shuō)法不無(wú)道理,,但是一般而言,對(duì)于一個(gè)比較大的系統(tǒng),,errmsg是比較大的,,所以產(chǎn)生副本導(dǎo)致執(zhí)行文件尺寸變大,,不僅增加了系統(tǒng)裝載時(shí)間,也會(huì)讓一個(gè)程序在內(nèi)存中占更多的頁(yè)面,。而對(duì)于errmsg這樣數(shù)據(jù),,一般來(lái)說(shuō),在系統(tǒng)運(yùn)行時(shí)不會(huì)經(jīng)常用到,,所以還是產(chǎn)生的內(nèi)存換頁(yè)也就不算頻繁,。權(quán)衡之下,還是只有一份errmsg的效率高,。即便是像logmsg這樣頻繁使用的的數(shù)據(jù),,操作系統(tǒng)的內(nèi)存調(diào)度算法會(huì)讓這樣的頻繁使用的頁(yè)面常駐于內(nèi)存,所以也就不會(huì)出現(xiàn)內(nèi)存換頁(yè)問(wèn)題了,。


11
,、出錯(cuò)信息的處理
—————————
你會(huì)處理出錯(cuò)信息嗎?哦,,它并不是簡(jiǎn)單的輸出,。看下面的示例:

if ( p == NULL ){
printf ( "ERR: The pointer is NULL\n" );
}

告別學(xué)生時(shí)代的編程吧,。這種編程很不利于維護(hù)和管理,,出錯(cuò)信息或是提示信息,應(yīng)該統(tǒng)一處理,,而不是像上面這樣,,寫成一個(gè)硬編碼。第10條對(duì)這方面的處理做了一部分說(shuō)明,。如果要管理錯(cuò)誤信息,,那就要有以下的處理:

/*
聲明出錯(cuò)代碼 */
#define ERR_NO_ERROR 0 /* No error */
#define ERR_OPEN_FILE 1 /* Open file error */
#define ERR_SEND_MESG 2 /* sending a message error */
#define ERR_BAD_ARGS 3 /* Bad arguments */
#define ERR_MEM_NONE 4 /* Memeroy is not enough */
#define ERR_SERV_DOWN 5 /* Service down try later */
#define ERR_UNKNOW_INFO 6 /* Unknow information */
#define ERR_SOCKET_ERR 7 /* Socket operation failed */
#define ERR_PERMISSION 8 /* Permission denied */
#define ERR_BAD_formAT 9 /* Bad configuration file */
#define ERR_TIME_OUT 10 /* Communication time out */

/*
聲明出錯(cuò)信息 */
char* errmsg[] = {
/* 0 */ "No error",
/* 1 */ "Open file error",
/* 2 */ "Failed in sending/receiving a message",
/* 3 */ "Bad arguments",
/* 4 */ "Memeroy is not enough",
/* 5 */ "Service is down; try later",
/* 6 */ "Unknow information",
/* 7 */ "A socket operation has failed",
/* 8 */ "Permission denied",
/* 9 */ "Bad configuration file format",
/* 10 */ "Communication time out",
};

/*
聲明錯(cuò)誤代碼全局變量 */
long errno = 0;

/*
打印出錯(cuò)信息函數(shù) */
void perror( char* info)
{
if ( info ){
printf("%s: %s\n", info, errmsg[errno] );
return;
}

printf("Error: %s\n", errmsg[errno] );
}

這個(gè)基本上是ANSI的錯(cuò)誤處理實(shí)現(xiàn)細(xì)節(jié)了,于是當(dāng)你程序中有錯(cuò)誤時(shí)你就可以這樣處理:

bool CheckPermission( char* userName )
{
if ( strcpy(userName, "root") != 0 ){
errno = ERR_PERMISSION_DENIED;
return (FALSE);
}

...
}

main()
{
...
if (! CheckPermission( username ) ){
perror("main()");
}
...
}

一個(gè)即有共性,,也有個(gè)性的錯(cuò)誤信息處理,,這樣做有利同種錯(cuò)誤出一樣的信息,統(tǒng)一用戶界面,,而不會(huì)因?yàn)槲募蜷_失敗,,A程序員出一個(gè)信息,B程序員又出一個(gè)信息,。而且這樣做,,非常容易維護(hù)。代碼也易讀,。

當(dāng)然,,物極必反,也沒(méi)有必要把所有的輸出都放到errmsg中,,抽取比較重要的出錯(cuò)信息或是提示信息是其關(guān)鍵,,但即使這樣,,這也包括了大多數(shù)的信息。


12
,、常用函數(shù)和循環(huán)語(yǔ)句中的被計(jì)算量
—————————————————
看一下下面這個(gè)例子:

for( i=0; i<1000; i++ ){
GetLocalHostName( hostname );
...
}

GetLocalHostName
的意思是取得當(dāng)前計(jì)算機(jī)名,,在循環(huán)體中,它會(huì)被調(diào)用1000次啊,。這是多么的沒(méi)有效率的事啊,。應(yīng)該把這個(gè)函數(shù)拿到循環(huán)體外,這樣只調(diào)用一次,,效率得到了很大的提高,。雖然,我們的編譯器會(huì)進(jìn)行優(yōu)化,,會(huì)把循環(huán)體內(nèi)的不變的東西拿到循環(huán)外面,,但是,你相信所有編譯器會(huì)知道哪些是不變的嗎,?我覺(jué)得編譯器不可靠,。最好還是自己動(dòng)手吧。

同樣,,對(duì)于常用函數(shù)中的不變量,,如:

GetLocalHostName(char* name)
{
char funcName[] = "GetLocalHostName";

sys_log( "%s begin......", funcName );
...
sys_log( "%s end......", funcName );
}

如果這是一個(gè)經(jīng)常調(diào)用的函數(shù),每次調(diào)用時(shí)都要對(duì)funcName進(jìn)行分配內(nèi)存,,這個(gè)開銷很大啊,。把這個(gè)變量聲明成static吧,當(dāng)函數(shù)再次被調(diào)用時(shí),,就會(huì)省去了分配內(nèi)存的開銷,,執(zhí)行效率也很好。


13
,、函數(shù)名和變量名的命名
————————————
我看到許多程序?qū)ψ兞棵秃瘮?shù)名的取名很草率,,特別是變量名,什么a,b,c,aa,bb,cc,,還有什么flag1,flag2, cnt1, cnt2,,這同樣是一種沒(méi)有修養(yǎng)的行為。即便加上好的注釋,。好的變量名或是函數(shù)名,,我認(rèn)為應(yīng)該有以下的規(guī)則:

1)
直觀并且可以拼讀,可望文知意,,不必解碼
2)
名字的長(zhǎng)度應(yīng)該即要最短的長(zhǎng)度,,也要能最大限度的表達(dá)其含義,。
3)
不要全部大寫,,也不要全部小寫,應(yīng)該大小寫都有,,如:GetLocalHostName 或是 UserAccount,。
4)
可以簡(jiǎn)寫,但簡(jiǎn)寫得要讓人明白,,如:ErrorCode -> ErrCode, ServerListener -> ServLisner,,UserAccount -> UsrAcct 等。
5)
為了避免全局函數(shù)和變量名字沖突,,可以加上一些前綴,,一般以模塊簡(jiǎn)稱做為前綴。
6)
全局變量統(tǒng)一加一個(gè)前綴或是后綴,,讓人一看到這個(gè)變量就知道是全局的,。
7)
用匈牙利命名法命名函數(shù)參數(shù),局部變量,。但還是要堅(jiān)持望文生意的原則,。
8)
與標(biāo)準(zhǔn)庫(kù)(如:STL)或開發(fā)庫(kù)(如:MFC)的命名風(fēng)格保持一致。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多