讀書筆記-C語言-函數(shù)

1氏仗、c語言的函數(shù)有以下特點(diǎn):

(1)才源程序由函數(shù)組成恬砂,一個主函數(shù)main()+若干其他函數(shù)

C程序中的函數(shù)類似文章中的段落篡殷,但與段落不同的是瞬内,程序的執(zhí)行是由main函數(shù)這一段起始卓箫,在main函數(shù)這一段中結(jié)束载矿,而不是由第一個函數(shù)起始,在最后一個函數(shù)中結(jié)束烹卒。main外的其他函數(shù)恢准,是由main調(diào)用執(zhí)行的。

(2)函數(shù)之間是調(diào)用的關(guān)系甫题,調(diào)用某函數(shù)的函數(shù)稱主調(diào)函數(shù)馁筐,被調(diào)用的函數(shù)稱為被調(diào)函數(shù)。main函數(shù)(我們)是主體坠非,有權(quán)調(diào)用其他函數(shù)敏沉,其他函數(shù)之間也可以相互調(diào)用以協(xié)調(diào)工作,例如餐廳也調(diào)用了打車。但其他函數(shù)不能調(diào)用main函數(shù)盟迟。

(3)除main函數(shù)外秋泳,其他函數(shù)都不能獨(dú)立運(yùn)行;其他函數(shù)只有在被調(diào)用時才運(yùn)行攒菠,不調(diào)用不運(yùn)行迫皱。

(4)同一函數(shù),可被反復(fù)多次調(diào)用辖众。

(5)函數(shù)的返回卓起,誰調(diào)用的返回誰

(6)函數(shù)分為兩種,系統(tǒng)提供的庫函數(shù)和自定義的函數(shù)

系統(tǒng)提供的庫函數(shù)如printf()凹炸、getchar()戏阅、sqrt()等,這些函數(shù)是由系統(tǒng)提供的啤它,隨時聽命由我們派遣奕筐。我們不必關(guān)心其內(nèi)部細(xì)節(jié),要調(diào)用他們变骡,只要包含相應(yīng)的頭文件(xxx.h)离赫。

(7)函數(shù)的參數(shù)和返回值。有的函數(shù)有1~多個參數(shù)塌碌,有的沒有參數(shù)笆怠。有的函數(shù)有1個返回值,有的沒有返回值誊爹。

函數(shù)的返回值有些類似數(shù)學(xué)中函數(shù)的函數(shù)值蹬刷,如sin(30)得到0.5,0.5就是函數(shù)sin(30)的返回值。60度的正弦值為0.866,0.866是sin(60)的返回值频丘。這說明參數(shù)不同办成,函數(shù)的返回值也可能不同。而有些函數(shù)有沒有返回值搂漠,如上例的"打車"函數(shù)迂卢,它只用于實(shí)現(xiàn)一些功能,并不需要返回什么東西桐汤。注意函數(shù)如果有返回值而克,返回值最多只能有1個。

2怔毛、函數(shù)的定義和調(diào)用

自己的函數(shù)必須先定義员萍,然后才能使用。

定義自己函數(shù)的一般形式如下所示:

函數(shù)返回值類型 ?函數(shù)名(參數(shù)類型1 ?參數(shù)名1拣度,參數(shù)類型2 ?參數(shù)名2碎绎,...)

{

語句1螃壤;

語句2;

....

}

注意:各個函數(shù)的定義是互相平行和獨(dú)立的筋帖,以上內(nèi)容必須與main函數(shù)或其他自定義函數(shù)并列奸晴。函數(shù)的定義不能嵌套,在一個函數(shù)體內(nèi)部不允許在定義另一個函數(shù)日麸。

在定義函數(shù)時寄啼,對于函數(shù)的頭部應(yīng)該注意以下問題:

(1)返回值類型,應(yīng)寫在函數(shù)名之前代箭,規(guī)定函數(shù)所返回的數(shù)據(jù)的類型墩划,如int、float梢卸、double走诞、char等副女。如果不寫返回值類型蛤高,表示規(guī)定返回值類型為int,不是沒有返回值碑幅。要規(guī)定函數(shù)沒有返回值戴陡,這一部分應(yīng)寫為關(guān)鍵字void,而不是省略沟涨。

(2)函數(shù)名是符合標(biāo)識符命名規(guī)則的名稱恤批,但最好"見名知意"。

(3)函數(shù)名后的()必不可少裹赴,即使函數(shù)沒有參數(shù)喜庞。

(4)在()內(nèi)規(guī)定函數(shù)的參數(shù),多個參數(shù)時參數(shù)之間以逗號分隔棋返。參數(shù)的定義與變量的定義類似延都,也是類型+參數(shù)名的形式(實(shí)際上參數(shù)確實(shí)可以被看做變量),但與變量定義不同的是睛竣,每個參數(shù)都必須在參數(shù)名前寫有類型晰房,且不寫分號(;)下面的定義是錯誤的int ?maxnum(int a,b){}在b之前也必須寫出b的類型射沟,不能省略殊者。

對于沒有參數(shù)的函數(shù),在函數(shù)的()中也可寫上void強(qiáng)調(diào)验夯。舉例:

void ?print(void){

}

兩個void含義是不同的猖吴,第一個void規(guī)定函數(shù)沒有返回值,第二個()中的void強(qiáng)調(diào)了函數(shù)沒有參數(shù)挥转。無參數(shù)函數(shù)的()內(nèi)寫不寫void都是可以的距误,但()萬萬不可省略簸搞。

函數(shù)的調(diào)用:

函數(shù)的調(diào)用方法:調(diào)用函數(shù)有兩種方式:(1)將函數(shù)調(diào)用作為獨(dú)立的語句:函數(shù)名(參數(shù),參數(shù)准潭,...)+分號(趁俊;),(2)在表達(dá)式中調(diào)用函數(shù):表達(dá)式....函數(shù)名(參數(shù)刑然,參數(shù)寺擂,...)。

對于有返回值的函數(shù)以上兩種調(diào)用方式均可泼掠,只是若采用第(1)中方式函數(shù)所返回的值就沒什么用了怔软,返回值返回后會被直接丟掉(但函數(shù)中的語句還是被正常執(zhí)行)。而對與無返回值的函數(shù)只能采用上面第(1)中調(diào)用方式择镇,因?yàn)楹瘮?shù)無返回值挡逼,表達(dá)式無法求值。如z=2*print()+1;

在表達(dá)式中調(diào)用函數(shù):例如:z=sqrt(4)*3;表示計(jì)算4的平方根腻豌,在*3后將6存入變量z中家坎,其中計(jì)算4的平方根是通過調(diào)用有返回值的系統(tǒng)庫函數(shù)sqrt完成的。對于有返回值的自定義函數(shù)也可以用類似的調(diào)用方式吝梅。這種調(diào)用方式就是講函數(shù)作為表達(dá)式的一部分虱疏,將來用函數(shù)的返回值替換這一部分參與表達(dá)式的計(jì)算。

注意:形參一定是變量苏携,實(shí)參既可以是常量做瞪,也可以是變量或表達(dá)式或函數(shù)。如int x=25,y=73;maxnum(x*3,y);

在調(diào)用函數(shù)時右冻,所給出的實(shí)參必須和形參在數(shù)量上装蓬、順序上、類型上嚴(yán)格一致纱扭,或類型上可以進(jìn)行轉(zhuǎn)換牍帚。

參數(shù)傳遞時,實(shí)參和形參是按照位置的先后順序一一對應(yīng)的跪但,對應(yīng)的實(shí)參和形參的類型應(yīng)一致履羞。如不一致,則以形參類型(函數(shù)定義頭部)為準(zhǔn)屡久,自動將實(shí)參轉(zhuǎn)換為改類型忆首。

函數(shù)調(diào)用的過程:

(1)每個函數(shù)都有自己獨(dú)立的內(nèi)存空間,函數(shù)中的變量包括形參都位于各自的內(nèi)存空間中被环,互不干涉糙及。被調(diào)函數(shù)的內(nèi)存空間只能在函數(shù)被調(diào)用后運(yùn)行時才存在,不調(diào)用不運(yùn)行其空間不存在筛欢。

(2)在調(diào)用函數(shù)時浸锨,主調(diào)函數(shù)暫停運(yùn)行唇聘,程序轉(zhuǎn)去執(zhí)行被調(diào)函數(shù)。在轉(zhuǎn)去執(zhí)行被調(diào)函數(shù)之前的準(zhǔn)備工作為柱搜,將形參當(dāng)做變量迟郎,在被調(diào)函數(shù)自己的內(nèi)存空間中開辟這些形參變量的空間,然后將實(shí)參的值單項(xiàng)的傳遞給對應(yīng)的形參變量聪蘸,即用實(shí)參值給形參變量賦值宪肖。

(3)運(yùn)行被調(diào)函數(shù),逐條執(zhí)行被調(diào)函數(shù)中的語句健爬,這與在main函數(shù)中的執(zhí)行方式一樣控乾。被調(diào)函數(shù)運(yùn)行結(jié)束后,被調(diào)函數(shù)的空間包括其中所有的變量娜遵,也包括形參變量全部消失蜕衡,它們的空間即可被系統(tǒng)回收不在存在(但對有返回值的函數(shù),返回值不會消失)设拟。

(4)返回到主調(diào)函數(shù)中剛才暫停的位置繼續(xù)運(yùn)行主調(diào)函數(shù)的后續(xù)程序慨仿。

(5)變量都要位于他所屬函數(shù)的空間中,而不能位于其他函數(shù)的空間中蒜绽。形參是被調(diào)函數(shù)中的變量镶骗,應(yīng)位于被調(diào)函數(shù)的空間中桶现。由于不同的函數(shù)有各自不同的空間躲雅,因此在不同的函數(shù)中可以使用同名變量,若實(shí)參是主調(diào)函數(shù)中的變量骡和,形參和實(shí)參也可以同名(形參是被調(diào)函數(shù)中的”變量“相赁,二者分屬不同的空間)。

函數(shù)的返回值:

函數(shù)被調(diào)用后慰于,可以沒有返回值钮科,也可以有1個返回值。

無論有無返回值婆赠,函數(shù)均可被調(diào)用绵脯,其調(diào)用過程也一致。函數(shù)結(jié)束后也都能返回到主調(diào)函數(shù)的調(diào)用處繼續(xù)運(yùn)行主調(diào)函數(shù)的后續(xù)程序休里。只不過對有返回值的函數(shù)蛆挫,在表達(dá)式中調(diào)用時,一般還要用返回值替換其中函數(shù)的調(diào)用部分妙黍,然后在計(jì)算表達(dá)式悴侵,例如z=sqrt(4)*3;sqrt(4)的返回值為2,用2替換sqrt(4)部分得z=2*3;在執(zhí)行此語句變量z被賦值為6.

sqrt是系統(tǒng)庫函數(shù)拭嫁,它的返回值是系統(tǒng)自動算出的可免。而對于自定義函數(shù)抓于,要返回值,就要由我們自己通過return語句讓函數(shù)返回一個值浇借。return是關(guān)鍵字捉撮,return語句的形式為:return ?表達(dá)式;或return ?(表達(dá)式)妇垢;

表達(dá)式的值將被算出呕缭,并將表達(dá)式的值作為函數(shù)的返回值返回。其執(zhí)行過程是:計(jì)算表達(dá)式的值修己,然后開辟一個臨時空間恢总,將表達(dá)式的值存入此臨時空間,再將此臨時空間中的值作為函數(shù)返回值返回給主調(diào)函數(shù)睬愤。

關(guān)于return語句片仿,還應(yīng)注意以下幾點(diǎn):

(1)同一函數(shù)內(nèi)允許出現(xiàn)多個return語句,但在函數(shù)每次被調(diào)用時只能有其中一個return語句被執(zhí)行尤辱,函數(shù)只能返回一個值砂豌。

(2)一旦執(zhí)行return,函數(shù)立即結(jié)束光督,如果本函數(shù)內(nèi)在return后還有其他語句則這些語句也不會被 執(zhí)行了兵多。也就是說return兼有返回值和強(qiáng)行跳出函數(shù)的雙重作用,它會使程序即刻返回到主調(diào)函數(shù)的調(diào)用處繼續(xù)運(yùn)行主調(diào)函數(shù)后面的程序品追。

(3)return語句還有一個用法衅胀,是:return;這種用法沒有表達(dá)式船老,不能返回值咖熟,僅起到強(qiáng)行跳出函數(shù)的這個作用。這種用法只能用于沒有返回值的函數(shù)柳畔。

(4)沒有返回值的函數(shù)既可以寫return馍管;語句,也可以不寫return薪韩;語句确沸。后者在函數(shù)語句全部運(yùn)行完畢之后,函數(shù)會自動結(jié)束俘陷,自動返回到主調(diào)函數(shù)罗捎。因此函數(shù)有、無返回值和有無return岭洲;語句并沒有什么必然關(guān)系宛逗。

實(shí)際上,即使有返回值的函數(shù)盾剩,也可以沒有return語句雷激,這樣在函數(shù)語句全部運(yùn)行完畢之后替蔬,函數(shù)將返回一個隨機(jī)值。但不建議這樣做屎暇,對有返回值的函數(shù)應(yīng)該寫有return 表達(dá)式承桥;的語句讓它返回一個值。如希望不寫return根悼,不如將函數(shù)定義為無返回值的(void)凶异。

(5)如果函數(shù)有返回值,則實(shí)際返回值的類型應(yīng)該和函數(shù)定義頭部的函數(shù)名前的類型一致剩彬,如不一致矿卑,則以函數(shù)定義頭部的函數(shù)名錢的類型為準(zhǔn),自動將return語句后的表達(dá)式值的類型轉(zhuǎn)換為定義頭部的類型然后在返回母廷。

main函數(shù)實(shí)際也是一個自定義函數(shù)轻黑,我們通常對main函數(shù)的寫法是:

main()

{

}

函數(shù)名main前的返回值類型省略琴昆,表示main函數(shù)式有返回值的且返回值是一個int型的數(shù)據(jù)。所以也可以將main函數(shù)寫為:

int ?main()

{

}

以上二者是等效的业舍。

main的返回值用于在程序結(jié)束后返回給操作系統(tǒng)(如Windows)表示程序運(yùn)行情況抖拦。我們可以在main函數(shù)中用return 0;或return 1勤讽;等向操作系統(tǒng)返回一個值(程序若正常結(jié)束一般返回0)脚牍。一般我們不必關(guān)心甚至也可以不向操作系統(tǒng)返回值巢墅,或者干脆規(guī)定main函數(shù)沒有返回值君纫,將main函數(shù)寫為下面的形式也是正確;

void ?main()

{

}

顯然一旦在main函數(shù)中執(zhí)行了return語句蓄髓,將跳出main函數(shù)会喝,那么整個程序也就運(yùn)行結(jié)束了玩郊。

函數(shù)的聲明:

程序中函數(shù)之間是調(diào)用與被調(diào)用的關(guān)系译红,因此函數(shù)彼此出現(xiàn)的先后順序無關(guān)緊要兴溜。拙徽。。已卷。

解決這個問題有兩種方法:一是像例子中先寫函數(shù)fun的定義淳蔼,然后在寫main函數(shù)鹉梨,在main函數(shù)中調(diào)用;還有一種方法是使用函數(shù)的聲明晌坤。

函數(shù)的聲明寫法非常簡單旦袋,就是函數(shù)定義的頭部“照抄”疤孕,后面再加分號(;)就可以了鹉戚。比如:void ?fun ?(int p);

它類似與一條語句专控,但不會產(chǎn)生任何操作伦腐,只是“告訴”編譯系統(tǒng),存在這樣一個函數(shù)(可能在后面定義)幸冻,讓編譯系統(tǒng)提前認(rèn)識這個函數(shù)嘁扼。

函數(shù)的聲明,也稱函數(shù)的原型聲明强缘,也稱函數(shù)的原型不傅。原型就是樣式访娶,它表示了函數(shù)的返回值類型、函數(shù)名秘车、形參個數(shù)叮趴、順序及每個形參的類型权烧。聲明函數(shù)就是告訴編譯系統(tǒng)這種函數(shù)的樣式,因?yàn)榫幾g系統(tǒng)需要這些信息來認(rèn)識這個函數(shù)妻率。

注意在函數(shù)的原型中宫静,有一樣?xùn)|西是可有可無的扔字,就是形參的名字革为。也就是說舵鳞,在函數(shù)的聲明中,形參的名字可以省略博其,但不能省略形參類型迂猴,除了形參名字之外沸毁,其他任何內(nèi)容均不可省略。如:void fun (int)携兵;

舉例:#includevoid fun(int p);

main()

{

int a=10;

fun(a);

printf("main:%d\n",a);

}

void fun(int p)

{

int a=2;

a=a*p;

printf("fun(1):%d\n",a);

if(a>0)return;

printf("fun(2):%d\n",a);

}

函數(shù)聲明的位置:

函數(shù)的聲明既可以出現(xiàn)在函數(shù)外徐紧,也可以出現(xiàn)在其他的函數(shù)體內(nèi)炭懊。兩者的區(qū)別如下所示:

在函數(shù)外聲明:使編譯系統(tǒng)從聲明之處開始到本源程序文件的末尾的所有函數(shù)中侮腹,都認(rèn)識該函數(shù)。

在函數(shù)內(nèi)聲明:使編譯系統(tǒng)僅在本函數(shù)內(nèi)呀潭、從聲明之處開始認(rèn)識該函數(shù)钠署,但在本函數(shù)之外有不認(rèn)識該函數(shù)荒椭。

程序中函數(shù)的聲明不是一定要有的趣惠。只有先調(diào)用函數(shù),后出現(xiàn)函數(shù)定義的時候草戈,才需要在調(diào)用之前聲明函數(shù)侍瑟。如果先出現(xiàn)函數(shù)的定義丙猬,后調(diào)用函數(shù)茧球,就可以不必聲明星持,當(dāng)然這種情況下聲明函數(shù)也不會出錯督暂。無論如何,我們的目的是在調(diào)用函數(shù)之前讓編譯系統(tǒng)認(rèn)識這個函數(shù)福侈,定義可以讓他認(rèn)識肪凛,聲明也可以讓他認(rèn)識辽社。對同一函數(shù)還可以聲明多次滴铅,但定義只能出現(xiàn)一次。

調(diào)用系統(tǒng)庫函數(shù)拱烁,也需要提前聲明函數(shù)戏自。但系統(tǒng)庫函數(shù)的函數(shù)聲明已被事先寫到頭文件(.h)中了伤锚,我們通常用#include命令在程序中包含對應(yīng)的頭文件屯援,就是把對應(yīng)函數(shù)的聲明包含到我們的程序中狞洋。這就是為什么在調(diào)用庫函數(shù)之前,一定要包括對應(yīng)頭文件的原因耳胎。例如:要調(diào)用庫函數(shù)sqrt(),就需包含頭文件math.h,因?yàn)閙ath.h中有sqrt函數(shù)的聲明怕午。

函數(shù)的嵌套調(diào)用和遞歸調(diào)用:

函數(shù)的嵌套調(diào)用:定義函數(shù)不允許嵌套淹魄,但調(diào)用函數(shù)可以嵌套甲锡,即在被調(diào)函數(shù)中又調(diào)用其他函數(shù)缤沦。

函數(shù)的遞歸調(diào)用:在一個函數(shù)中可以調(diào)用其他函數(shù),那么如果在一個函數(shù)中調(diào)用自己這個函數(shù)本身又會如何呢包蓝?在程序設(shè)計(jì)中测萎,函數(shù)自己調(diào)用自己不僅是合法的届巩,而且是一個非常重要的程序設(shè)計(jì)技巧稱為遞歸恕汇。例如:

int ?fun(int x)

{

.....

fun(y);

....

}

變量的作用域及存儲類別:

變量作用域:作用域是指變量在程序中能夠起作用的地域范圍瘾英。

變量既可以在函數(shù)內(nèi)定義,也可以在函數(shù)外定義月腋。在函數(shù)內(nèi)定義的變量為局部變量(也稱內(nèi)部變量)榆骚,在函數(shù)外定義的變量為全局變量(也稱外部變量)煌集。

局部變量:

形參在函數(shù)被調(diào)用時苫纤,也作為函數(shù)內(nèi)的局部變量。

局部變量的特點(diǎn):

(1)只在本函數(shù)內(nèi)有效祝高,在其他函數(shù)中都不能直接使用污筷。

(2)局部變量若在定義時未賦初值瓣蛀,初值為隨機(jī)數(shù)惋增。

(3)不同函數(shù)中可使用同名變量,它們互不干擾林束。形參和實(shí)參也可以同名诊县。

(4)函數(shù)執(zhí)行結(jié)束后措左,變量空間被回收怎披。

局部變量是在函數(shù)內(nèi)定義的變量凉逛,還可以讓它更局部一些,在復(fù)合語句(一對{}括起的語句)內(nèi)還可以定義局部變量毫胜。這種局部變量的作用范圍更小酵使,僅在所在的復(fù)合語句范圍內(nèi)有效口渔,而且其生存期也在復(fù)合語句范圍內(nèi)穿撮,一旦復(fù)合語句執(zhí)行結(jié)束,其空間就被回收业踢。

全局變量:在函數(shù)外定義的變量為全局變量(也稱外部變量)陨亡。全局變量的重要特點(diǎn):

(1)這種變量的作用范圍是“全局的”

深员,從它定義處開始到本源程序文件末尾的所有函數(shù)都共享此變量倦畅。

(2)如定義時未賦初值叠赐,初值自動為0屡江,而不是隨機(jī)數(shù)惩嘉。

如果函數(shù)內(nèi)有局部變量與全局變量同名文黎,則在該局部變量的作用范圍內(nèi)將使用該局部變量,同名全局變量被屏蔽不起作用桩蓉。

全局變量的優(yōu)點(diǎn)是在多個函數(shù)中都能同時起作用院究,在一個函數(shù)中對某變量值的改變可被帶到其他函數(shù)中业汰,所以通過全局變量可在不同函數(shù)間傳遞數(shù)據(jù)蔬胯。

擴(kuò)大全局變量的作用域:全局變量的作用域有一個限制位他,就是只能從變量的定義處之后才能被使用。

舉例:#includeint sum;

void fun1()

{

sum+=20;

}

int a;

void fun2()

{

a=20;sum+=a;

}

main()

{

sum=0;

fun1();

a=8;

fun2();

printf("sum=%d,a=%d",sum,a);

}

上例中fun1函數(shù)式不能使用全局變量a的京景,因?yàn)閍在fun1之后才定義确徙。如果一定要在fun1函數(shù)中使用全局變量a,能不能辦到呢鄙皇?可以伴逸,這需要用關(guān)鍵字extern來擴(kuò)大其作用范圍膘壶。extern是用來聲明全局變量的颓芭,在用extern聲明全局變量之后亡问,就可以使用該全局變量了(盡管他可能在以后才被定義)。聲明的寫法與變量定義的寫法基本相同万矾,只是在之前加extern良狈,例如:extern ?int ?a; 舉例:如下

注意變量的聲明與變量的定義不同薪丁,聲明不會開辟變量的存儲空間严嗜,而定義就要開辟存儲空間了洲敢。因此全局變量的聲明可出現(xiàn)多次,而定義只能是一次渗常。

#includeextern int a;

int sum;

void fun1()

{

sum+=20;

/*在fun1函數(shù)中可以使用全局變量a*/

}

int? a;

void fun2()

...

只有先使用全局變量皱碘,后定義的才有必要聲明癌椿。如果全局變量是先出現(xiàn)的定義踢俄,而后才使用的送粱,可不必聲明抗俄,當(dāng)然如果聲明了也不會出錯动雹。

多文件編程:

當(dāng)一個c程序由多個源文件組成時胰蝠,注意多個源文件組成的是一個程序茸塞,而不是多個程序查剖。因此只能在一個源文件中有main函數(shù)笋庄,且只能有一個main函數(shù)直砂。

file1.c如下

int a;/*全局變量*/

extern void fun();

main()

{

a=10;

printf("(1)a=%d\n",a);

fun();

printf("(2)a=%d\n",a);

}

file2.c如下:

extern int a;

void fun()

{

a=20;

printf("fun中a=%d\n",a);

}

注意:(1)在一個文件中定義了全局變量静暂,有時希望在其他文件中也能使用該全局變量洽蛀。這時要在使用該變量的其他文件中聲明該變量。比如:file1.c中定義了全局變量a听绳,在file2.c中應(yīng)該先用extern聲明全局變量a异赫,才能在file2.c中使用file1.c中的a塔拳。

(2)調(diào)用其他文件中定義的函數(shù)也要聲明靠抑。比如:在main函數(shù)中調(diào)用了其他文件的fun函數(shù)颂碧,因此在file1.c的第二行事先聲明了fun函數(shù) extern ?void fun();這時的extern用在函數(shù)聲明前载城,它表示該函數(shù)是在其他文件中定義的诉瓦。extern也可以省略,編譯系統(tǒng)會自動 先查找本文件中有無此函數(shù)的定義睬澡,如未找到再到其他文件中查找固额。

(3)在函數(shù)定義的頭部還可以加extern以強(qiáng)調(diào)該函數(shù)允許被其他文件調(diào)用,如上例file2.c中對函數(shù)fun的定義還可以寫為:extern void fun()

{

a=20;

printf("fun中a=%d\n",a);

}

通常函數(shù)定以前的extern可以省略煞聪,其效果是相同的斗躏。

總結(jié)extern的用法和作用:

(1)全局變量的聲明或函數(shù)的聲明前加extern,表示該全局變量或函數(shù)是其他文件中定義的米绕,或是本文件稍后定義的瑟捣,這里extern用于擴(kuò)大作用域范圍。注意聲明并不開辟變量空間迈套。

(2)函數(shù)定義前加extern或不寫extern,都表示該函數(shù)允許被其他文件調(diào)用碱鳞。

如果不讓其他文件調(diào)用本文件定義的全局變量或函數(shù)桑李,該如何做呢?在全局變量的定義或函數(shù)定義前加static,可限制其只能在本文件中使用贵白,不允許在其他文件中使用率拒,即使在其他文件中使用extern聲明也不行例如:static ?int a;

static ?int ?MyFun(int a, int b)

{

}

允許被其他文件調(diào)用的函數(shù)稱為外部函數(shù),不允許被其他文件調(diào)用的函數(shù)稱為內(nèi)部函數(shù)禁荒。

注意:若允許被其他文件使用猬膨,函數(shù)在定義時不寫static也可以,或加extern強(qiáng)調(diào)也可以呛伴。但對于全局變量勃痴,定義時只能不寫static,不能加extern強(qiáng)調(diào)热康。如果加了就是聲明變量而不是定義變量了沛申,會導(dǎo)致變量未定義的錯誤。

總結(jié)static的用法和作用:

(1)全局變量定義時或函數(shù)定義時加static姐军,表示限制其只允許在本文件內(nèi)被使用铁材,不允許在其他文件中被使用。

(2)局部變量定義前加static奕锌,表示靜態(tài)變量著觉。

變量的存儲類別:

存儲類別表示變量在計(jì)算機(jī)中的存儲位置,有3中存儲位置分別是:內(nèi)存動態(tài)存儲區(qū)歇攻、內(nèi)存靜態(tài)存儲區(qū)固惯、cpu寄存器。

在定義變量時缴守,如何指定變量的存儲類別呢(這里僅指局部變量,全局變量除外)镇辉?

(1)在定義變量時屡穗,變量名前用關(guān)鍵字auto,則變量將位于內(nèi)存動態(tài)存儲區(qū)忽肛,這種變量也稱自動型變量村砂。

(2)在定義變量時,變量名前用關(guān)鍵字static屹逛,則變量將位于內(nèi)存靜態(tài)存儲區(qū)础废,這種變量也稱靜態(tài)性變量。

(3)在定義變量時罕模,變量名前用關(guān)鍵字register评腺,則變量將位于CPU寄存器,這種變量也稱寄存器型變量淑掌。

auto可以省略蒿讥,也就是說,如在定義變量時沒有寫出以上3中關(guān)鍵字的任何一種,則該變量為auto型芋绸,與寫出auto是等效的媒殉。

舉例:

auto ?int a;/*或?qū)憺閕nt ?a;auto a;*/

static int b;/*或?qū)憺閟tatic b;*/

register int c;/*或?qū)憺閞egister c;*/

以上3個變量分別位于內(nèi)存動態(tài)存儲區(qū)、內(nèi)存靜態(tài)存儲區(qū)摔敛、CPU寄存器中廷蓉,其中,auto可以省略马昙,在寫出auto桃犬、static、register且變量為int型是给猾,int也可以省略疫萤。

注意:位于CPU寄存器中的變量,是沒有在內(nèi)存中的敢伸,當(dāng)然也沒有地址扯饶,因此不能用&取地址。

不同存儲類別變量的特點(diǎn):


注意:register型變量的速度要遠(yuǎn)遠(yuǎn)快于其他存儲類別的變量

重新初始化:是指如果函數(shù)中一個變量在定義時賦了初值池颈,則每次調(diào)用這個函數(shù)都要重新為變量賦初值尾序。

只初始化一次:是指在本函數(shù)被多次調(diào)用時,只有第一次被調(diào)用才給變量賦初值躯砰,該函數(shù)以后再被調(diào)用不會再給變量重新賦初值每币。

局部變量和全局變量的存儲類別:

(1)全局變量:只能是static型的,即只能位于內(nèi)存靜態(tài)存儲區(qū)琢歇。

(2)函數(shù)中兰怠,或{}中的局部變量:可以使auto、static或register型的李茫。

(3)函數(shù)的形參:可以是auto或register型的揭保,不能為static型的。

注意:在定義全局變量時魄宏,有無static都是靜態(tài)的秸侣,如有static則是另外的含義,它不允許被其他源文件使用宠互。

預(yù)編譯處理:

c源程序的運(yùn)行要經(jīng)過編譯味榛、鏈接兩個階段。這里講的預(yù)編譯在編譯之前予跌,也就是預(yù)編譯處理-編譯-鏈接搏色。編譯系統(tǒng)一般都是把預(yù)編譯、編譯兩個階段一起完成匕得,因此在上機(jī)操作時一般我們感覺不到預(yù)編譯的存在继榆。直接單擊編譯按鈕就可以了巾表,編譯系統(tǒng)會自動先預(yù)編譯,在編譯略吨。

預(yù)編譯處理集币,也稱編譯預(yù)處理。顧名思義翠忠,就是在編譯之前所做的工作鞠苟。

預(yù)編譯處理有三類:包含文件(#include)、宏定義(#define秽之、#undef)和條件編譯(#if当娱,#elif,#else,#ifedf,#ifndef,#endif)。預(yù)編譯處理不是執(zhí)行語句考榨,只能稱其為"命令"跨细。

(1)預(yù)編譯命令單獨(dú)占一行,以#號開頭河质,后無分號(冀惭;)。

(2)先預(yù)處理掀鹅,在編譯散休。

(3)預(yù)編譯命令本身不編譯。

宏定義:

我們學(xué)習(xí)過的符號常量就是一種宏定義乐尊,例如:#define PI 3.14戚丸。它的含義是將PI定義為文本3.14的代替符號,源程序中所有PI都將首先被替換為3.14扔嵌,然后在編譯限府,這樣所編譯的內(nèi)容中就不在有PI而只有3.14,編譯的是3.14而不是PI痢缎。

#define命令的用法是:#define ?宏名 ?替換文本

它是一個命令谣殊,而不是語句,稱為宏定義牺弄。宏定義的含義是用一個宏名去代替一個替換文本。宏名是個標(biāo)識符宜狐,符合標(biāo)識符命名規(guī)則的任意名稱都可以势告。

在編譯預(yù)處理時,將對源程序中的所有宏名都用替換文本去代換抚恒,稱為宏代換或宏展開咱台,然后在對代換后的內(nèi)容進(jìn)行編譯。

#define命令必須寫在函數(shù)外俭驮,其作用域?yàn)閺拿钇鸬皆闯绦蚪Y(jié)束回溺。

宏定義的替換文本可以是任意文本春贸,而不僅限于數(shù)字。預(yù)處理時不做語法檢查遗遵,只有在宏展開以后編譯時萍恕,在對宏展開以后的內(nèi)容做語法檢查。

注意宏展開時沒有任何計(jì)算的過程车要。

在源程序中引號之內(nèi)的宏名是不會被替換的允粤。例如:#define N 3+5 則語句printf("N");仍在屏幕上輸出N本身翼岁,引號內(nèi)的N不會被替換為3+5.

在宏定義命令的行尾是不加分號(类垫;)的。若加分號(琅坡;)悉患,對宏定義命令本身系統(tǒng)并不報錯,只不過在宏展開時榆俺,分號也會被視為替換文本的一部分售躁,將跟隨一起替換。只要保證替換后的內(nèi)容無語法錯就可以了谴仙。

(1)無參宏定義

(2)帶參宏定義

文件包含:

文件包含命令是#include迂求,它也是預(yù)編譯處理的一種。例如:#include <stdio.h> ? ? #inluce ?"Math.h"

文件包含是指將另一文件的內(nèi)容包含到當(dāng)前文件的#include命令的地方晃跺,取代#include命令行揩局。如同將另一個文件打開、全選掀虎、復(fù)制凌盯,在到#include命令的地方粘貼一般。

所包含文件的文件名可用一對<>括起烹玉,也可用""括起驰怎。其區(qū)別是:<>表示所包含的文件位于系統(tǒng)文件夾中;""表示位于用戶文件夾中(一般與本C源程序同一文件夾)二打,當(dāng)使用""時县忌,若在用戶文件夾中沒有找到要包含的文件,計(jì)算機(jī)會自動再去系統(tǒng)文件夾中查找继效。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末症杏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子瑞信,更是在濱河造成了極大的恐慌厉颤,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凡简,死亡現(xiàn)場離奇詭異逼友,居然都是意外死亡精肃,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門帜乞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來司抱,“玉大人,你說我怎么就攤上這事挖函∽粗玻” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵怨喘,是天一觀的道長津畸。 經(jīng)常有香客問我,道長必怜,這世上最難降的妖魔是什么肉拓? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮梳庆,結(jié)果婚禮上暖途,老公的妹妹穿的比我還像新娘。我一直安慰自己膏执,他們只是感情好驻售,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著更米,像睡著了一般欺栗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上征峦,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天迟几,我揣著相機(jī)與錄音,去河邊找鬼栏笆。 笑死类腮,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛉加。 我是一名探鬼主播蚜枢,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼针饥!你這毒婦竟也來了祟偷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤打厘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后贺辰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體户盯,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嵌施,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了莽鸭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吗伤。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖硫眨,靈堂內(nèi)的尸體忽然破棺而出足淆,到底是詐尸還是另有隱情,我是刑警寧澤礁阁,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布巧号,位于F島的核電站,受9級特大地震影響姥闭,放射性物質(zhì)發(fā)生泄漏丹鸿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一棚品、第九天 我趴在偏房一處隱蔽的房頂上張望靠欢。 院中可真熱鬧,春花似錦铜跑、人聲如沸门怪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掷空。三九已至,卻和暖如春伞广,著一層夾襖步出監(jiān)牢的瞬間拣帽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工嚼锄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留减拭,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓区丑,卻偏偏與公主長得像拧粪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沧侥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容