我們?cè)贑語(yǔ)言的學(xué)習(xí)和使用過(guò)程中經(jīng)常犯一些小錯(cuò)誤或者有很大的疑問(wèn),今天特把這些常見(jiàn)問(wèn)題總結(jié)如下,以饗讀者。
1. 始化問(wèn)題
int a[100]={0};能否將數(shù)組中所有的元素初試化為零?
答案是肯定的。因?yàn)樵跒閿?shù)組初始化的時(shí)候,若作者提供的初始化元素個(gè)數(shù)小于數(shù)組長(zhǎng)度,系統(tǒng)自動(dòng)會(huì)將其余元素的值定為0。像例子中,初始化時(shí)作者只提供了一個(gè)元素0給了a,還有99個(gè)元素作者沒(méi)有給出初始值。這時(shí)按照上面的規(guī)則系統(tǒng)會(huì)自動(dòng)將剩余元素的初始值定為0。以此我們可以得到數(shù)組中所有元素初始化為0的結(jié)果。
但我們不提倡這樣的做法。一般初始化可以用for循環(huán)來(lái)實(shí)現(xiàn)。
例:Int I,a[10];
For(I=0;I<10;I++)
Scanf(\"%d\",a[I]);
2. “文件包含”處理的兩種形式的差異
C語(yǔ)言提供了#include命令來(lái)實(shí)現(xiàn)“文件包含”的操作。
其一般形式為:①#include\"stdio.h\"
②#include<stdio.h>
程序運(yùn)行的時(shí)候,①首先在用戶當(dāng)前目錄中尋找要包含的文件,若找不到再按標(biāo)準(zhǔn)方式在相對(duì)路徑下找stdio.h,找不到再到path里面找,而②系統(tǒng)到存放c庫(kù)函數(shù)頭文件所在的目錄中尋找索要包含的文件,這是標(biāo)準(zhǔn)形式。
一般說(shuō),若為調(diào)用庫(kù)函數(shù)而用#include命令來(lái)包含相關(guān)的頭文件,則用②形式以節(jié)省時(shí)間。若要包含的使用使用戶自己編寫(xiě)的文件,一般用①形式。若文件不在當(dāng)前目錄中,①內(nèi)可以給出文件路徑。
3. 宏使用問(wèn)題
宏替換一般在編譯前,所以沒(méi)有分配任何的空間,沒(méi)有任何的類型可言,同時(shí)它是直接替換宏標(biāo)號(hào),所以使用一定要小心。例如:#definef(x)x*x
main( )
{int i;
i= f(2+3);
printf(\"%d\n\",i);
}
輸出結(jié)果是11而不是25,因?yàn)樗皇呛?jiǎn)單替換,替換的結(jié)果是2+3×2+3,所以輸出結(jié)果是11而不是25。
有些人過(guò)分地喜歡用宏,其實(shí)宏的使用也不是越多越好,要防止代碼的膨脹,現(xiàn)在的操作系統(tǒng)基本都是頁(yè)式管理,當(dāng)宏替換內(nèi)容過(guò)大發(fā)生換頁(yè)時(shí),宏的效率不會(huì)比調(diào)用函數(shù)快,還好c++ inline解決了這個(gè)問(wèn)題。
4. 空函數(shù)
void f();
void f(void);
void f(...);
通常我理解的空有如下三種形式,它們的含義分別是:
第一個(gè)函數(shù)的參數(shù)列表不是為空(C++里面是空),它的參數(shù)是不確定。
第二個(gè)函數(shù)參數(shù)才為空。
第三個(gè)函數(shù)是可變參數(shù)函數(shù),很多庫(kù)函數(shù)都是這樣實(shí)現(xiàn)的,如:典型的printf(...)。
5. C語(yǔ)言中的參數(shù)值的傳遞
C語(yǔ)言里面只有值傳遞,即實(shí)參的值傳給形參(單向傳遞)。那么有些人會(huì)問(wèn),那為什么用數(shù)組名或數(shù)組元素作函數(shù)參數(shù)的時(shí)候我們可以實(shí)現(xiàn)形參的值傳遞給實(shí)參呢?
那是因?yàn)橐话阕兞孔龊瘮?shù)參數(shù)時(shí),形參在調(diào)用時(shí)系統(tǒng)要為他分配存儲(chǔ)空間,實(shí)參與形參各自占用自己的存儲(chǔ)空間,實(shí)參的值再?gòu)?fù)制給形參。數(shù)組名或數(shù)組元素作函數(shù)參數(shù)時(shí),在進(jìn)行存貯空間的分配時(shí),不再為形參另外分配存儲(chǔ)空間了,實(shí)參與形參共占用同一空間。其實(shí)它本質(zhì)上也是值傳遞,即形參的值傳給形參,只是傳的實(shí)參的地址而不是參變量的值而已。
6. 數(shù)組越界問(wèn)題
C語(yǔ)言為了追求最大的靈活和效率,不對(duì)數(shù)組進(jìn)行邊界檢查,這些工作都是程序員自己的事情,不要以為你一越界編譯器就會(huì)告訴你,只有當(dāng)越界到編譯器需要換頁(yè)的時(shí)候才會(huì)報(bào)錯(cuò)。在理想情況下,Window下可以越界64K,不過(guò)很不幸,我試過(guò)很多次,最多達(dá)到了30k。不過(guò)這個(gè)數(shù)字也是很恐怖的,30k的匯編代碼足以對(duì)你的操作系統(tǒng)做任何事情。
7. 數(shù)組和指針
首先必須要搞清楚一個(gè)問(wèn)題,數(shù)組是數(shù)組,指針是指針,它們不是一回事。
int a[100];
int *p ;
a數(shù)組名代表數(shù)組的地址值是個(gè)常量,它不能夠被改變,而p是可以的。
看看sizeof(a) = 100 和sizeof(p) = 4(vc6.0)
對(duì)于字符串還要看看sizeof和strlen的區(qū)別:
sizeof還是數(shù)組的大小,strlen以0結(jié)束(不包括0)。大家一定要注意,因?yàn)椴蛔⒁獬霈F(xiàn)問(wèn)題,你都不知道怎么回事。
如:
void f( char * p )
{
if ( p == NULL )
{
return ;
}
char *t ;
int lenOfP = strlen(p);
t = ( char *) malloc( sizeof(char) * lenOfP );
strcpy ( t , p ) ;
.
.
}
8. malloc 與free
malloc free使用一般有幾個(gè)原則:
(1) malloc free必須配套使用,并且盡可能逆序。
(2) 誰(shuí)malloc的誰(shuí)free。
(3) 能夠不動(dòng)態(tài)分配的盡量不動(dòng)態(tài)分配,動(dòng)態(tài)分配是很費(fèi)時(shí)間的,而且存在一定的風(fēng)險(xiǎn)。
很多人喜歡這樣寫(xiě)程序:
type * f()
{
type *t = (type*)malloc ( sizeof(type));
.
.
return t ;
}
這樣肯定會(huì)出問(wèn)題,一般像這種情況,一般聲明f(type* t),誰(shuí)調(diào)用它誰(shuí)為t分配空間,誰(shuí)來(lái)釋放它的空間。不過(guò)很有意思的是,如char* asctime(),它返回一個(gè)表示時(shí)間的字符指針,但是并不要求你釋放,你也沒(méi)有辦法釋放,但是我可以肯定它這個(gè)串肯定不是在堆區(qū)分配的。
free的順序也很重要,很多時(shí)候free的時(shí)候會(huì)出現(xiàn)空指針的引用,不足為齊。有人提議free(t);t=NULL;這種用法有一定的道理,當(dāng)你free一塊空間后,操作系統(tǒng)不會(huì)立即回收,所以在你再次用t的時(shí)候可能還是可以用的,t就成了個(gè)野指針,而將其t=NULL后,對(duì)t的引用會(huì)出問(wèn)題。