函數(shù)和編譯預(yù)處.ppt_第1頁(yè)
函數(shù)和編譯預(yù)處.ppt_第2頁(yè)
函數(shù)和編譯預(yù)處.ppt_第3頁(yè)
函數(shù)和編譯預(yù)處.ppt_第4頁(yè)
函數(shù)和編譯預(yù)處.ppt_第5頁(yè)
已閱讀5頁(yè),還剩100頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第8章 函數(shù)和編譯預(yù)處理,C語(yǔ)言是一種結(jié)構(gòu)化程序設(shè)計(jì)語(yǔ)言,而結(jié)化程序設(shè)計(jì)的總體思想是采用模塊化結(jié)構(gòu),自上而下,逐步求精。即首先把一個(gè)復(fù)雜的大問(wèn)題分解為若干相對(duì)獨(dú)立的小問(wèn)題,如果小問(wèn)題仍較復(fù)雜,則可以把這些小問(wèn)題又繼續(xù)分解成若干子問(wèn)題,這樣不斷地分解,使得小問(wèn)題或子問(wèn)題簡(jiǎn)單到能夠直接用程序的三種基本結(jié)構(gòu)表達(dá)為止。然后,對(duì)應(yīng)每一個(gè)小問(wèn)題或子問(wèn)題編寫(xiě)出一個(gè)功能上相對(duì)獨(dú)立的程序塊來(lái),這種像積木一樣的程序塊被稱(chēng)為模塊。,前面各章中介紹的程序,都只有1個(gè)主函數(shù)main()。實(shí)際上,1個(gè)較大的應(yīng)用程序,按結(jié)構(gòu)化程序設(shè)計(jì)的要求,往往需要分成多個(gè)模塊。C語(yǔ)言是通過(guò)函數(shù)實(shí)現(xiàn)模塊化程序設(shè)計(jì)的,所以1個(gè)大的C語(yǔ)言程序,是有多個(gè)函數(shù)組成的,每個(gè)函數(shù)分別對(duì)應(yīng)各自的功能模塊。 在這些函數(shù)中,可以調(diào)用C編譯系統(tǒng)提供的庫(kù)函數(shù),也可以調(diào)用自己編寫(xiě)的、或別人編寫(xiě)的自定義函數(shù)。 函數(shù)的分類(lèi): 從用戶角度分為: 由系統(tǒng)提供標(biāo)準(zhǔn)函數(shù)(庫(kù)函數(shù))和用戶自定義函數(shù) 從函數(shù)形式分為: 無(wú)參函數(shù)和有參函數(shù),8.1 函數(shù)的定義與調(diào)用,8.1.1函數(shù)的定義 1任何函數(shù)(包括主函數(shù)main())都是由函數(shù)說(shuō)明和函數(shù)體兩部分組成。根據(jù)函數(shù)是否需要參數(shù),可將函數(shù)分為無(wú)參函數(shù)和有參函數(shù)兩種。 (1)無(wú)參函數(shù)的一般形式 函數(shù)類(lèi)型 函數(shù)名( void ) 說(shuō)明語(yǔ)句部分; 可執(zhí)行語(yǔ)句部分; 例如:void fun(void) printf(“ C programn”); ,(2)有參函數(shù)的一般形式 函數(shù)類(lèi)型 函數(shù)名( 數(shù)據(jù)類(lèi)型 參數(shù),數(shù)據(jù)類(lèi)型 參數(shù)2 ) 說(shuō)明語(yǔ)句部分; 可執(zhí)行語(yǔ)句部分; 有參函數(shù)比無(wú)參函數(shù)多了一個(gè)參數(shù)表。調(diào)用有參函數(shù)時(shí),調(diào)用函數(shù)將賦予這些參數(shù)實(shí)際的值。 為了與調(diào)用函數(shù)提供的實(shí)際參數(shù)區(qū)別開(kāi),將函數(shù)定義中的參數(shù)表稱(chēng)為形式參數(shù)表,簡(jiǎn)稱(chēng)形參表。 (3)空函數(shù)既無(wú)參數(shù)、函數(shù)體又為空的函數(shù)。其一般形式為: 函數(shù)類(lèi)型 函數(shù)名(void) ,例題8.1 定義一個(gè)函數(shù),用于求兩個(gè)數(shù)中的大數(shù)。 /*功能:定義一個(gè)求較大數(shù)的函數(shù)并在主函數(shù)中調(diào)用*/ int max(int n1, int n2) /*定義一個(gè)函數(shù)max(),n1,n2為形參*/ int z; z=n1n2?n1:n2; /*返回n1,n1中較大者 */ return (z) main() int max(int n1, int n2); /*函數(shù)說(shuō)明與函數(shù)定義第一行一樣寫(xiě),但在最后加;*/ int num1,num2; /*num1,num2是實(shí)際參數(shù)*/ printf(“input two numbers:n“); scanf(“%d%d“, /*使程序暫停,看結(jié)果。按任一鍵繼續(xù)*/ ,運(yùn)行情況: 6 9 max=9,2說(shuō)明:,(1)函數(shù)類(lèi)型:指出return語(yǔ)句返回值的類(lèi)型,它可以是C語(yǔ)言中任意合法的數(shù)據(jù)類(lèi)型。如:int float char等,函數(shù)類(lèi)型缺省時(shí),系統(tǒng)默認(rèn)為int 型。 (2)函數(shù)名:是一個(gè)標(biāo)識(shí)符。標(biāo)識(shí)函數(shù)的名稱(chēng)。 (3)函數(shù)名后括號(hào)內(nèi)是形式參數(shù),寫(xiě)出參數(shù)的類(lèi)型和名字。 如:int max(int n1, int n2);不能寫(xiě)成:int max(int n1, n2); (4)在老版本C語(yǔ)言中,參數(shù)類(lèi)型說(shuō)明允許放在函數(shù)說(shuō)明部分單獨(dú)指定。 例如: int max(n1, n2); int n1,n2; ,(5)一個(gè)C程序由一個(gè)main主函數(shù)和多個(gè)子函數(shù)組成,執(zhí)行從main函數(shù)開(kāi)始,調(diào)用其他函數(shù)后,返回到main函數(shù),在main函數(shù)中結(jié)束整個(gè)程序的運(yùn)行。 (6)函數(shù)定義不允許嵌套。 在語(yǔ)言中,所有函數(shù)(包括主函數(shù)main())都是平行的。一個(gè)函數(shù)的定義,可以放在程序中的任意位置,主函數(shù)main()之前或之后。但在一個(gè)函數(shù)的函數(shù)體內(nèi),不能再定義另一個(gè)函數(shù),即不能嵌套定義。,8.1.2 函數(shù)的返回值與函數(shù)類(lèi)型,語(yǔ)言的函數(shù)兼有其它語(yǔ)言中的函數(shù)和過(guò)程兩種功能,從這個(gè)角度看,又可把函數(shù)分為有返回值函數(shù)和無(wú)返回值函數(shù)兩種。 1函數(shù)返回值與return語(yǔ)句 有參函數(shù)的返回值,是通過(guò)函數(shù)中的return語(yǔ)句來(lái)獲得的。當(dāng)然有參函數(shù)如果不需要返回值,也可以沒(méi)有return語(yǔ)句。 (1)return語(yǔ)句的一般格式: return ( 返回值表達(dá)式 ); 或return返回值表達(dá)式; (2)return語(yǔ)句的功能:返回調(diào)用函數(shù),并將“返回值表達(dá)式”的值帶給調(diào)用函數(shù)。 (3) 一個(gè)函數(shù)中可以有一個(gè)以上的return語(yǔ)句,執(zhí)行到哪一個(gè)return語(yǔ)句,哪一個(gè)語(yǔ)句起作用。 (4)被調(diào)用函數(shù)中可以無(wú)return語(yǔ)句,當(dāng)無(wú)return語(yǔ)句時(shí)并不是不返回一個(gè)值,而是一個(gè)不確定的值。為了明確表示不返回值,可以用“void”定義成“無(wú)(空)類(lèi)型”。,例題8.2“void”定義的“無(wú)(空)類(lèi)型”函數(shù)的舉例 void f1(int x,int y) /*定義f1函數(shù),形參有整型的x、y,void表示空類(lèi)型*/ int w; w=x+y; printf(“w=%dn”,w); main() int a,b; a=3; b=4; f1(a,b);/*函數(shù)的調(diào)用,實(shí)參是整型的a、b*/ ,2函數(shù)類(lèi)型 在定義函數(shù)時(shí),對(duì)函數(shù)類(lèi)型的說(shuō)明,應(yīng)與return語(yǔ)句中返回值表達(dá)式的類(lèi)型一致。如果不一致,則以函數(shù)類(lèi)型為準(zhǔn)。如果缺省函數(shù)類(lèi)型,則系統(tǒng)一律按整型處理。,例題8.3返回值類(lèi)型和函數(shù)類(lèi)型不同,以函數(shù)為準(zhǔn)。 /*例題源代碼文件名:LT8_3.C*/ int max(float n1,float n2) float z; z=n1n2?n1:n2; return (z) ; /*返回n1,n1中較大者 */ main() float a,b; int c; scanf(“%f,%f”, ,運(yùn)行情況: 1.5 4.5 max=4 max函數(shù)中return (z);z返回值是float型,而函數(shù)定義返回值類(lèi)型是int型,以函數(shù)為準(zhǔn),所以是int型,運(yùn)行結(jié)果是max=4。,8.1.3 對(duì)被調(diào)用函數(shù)的說(shuō)明和函數(shù)原型,1如果調(diào)用庫(kù)函數(shù),不用說(shuō)明,但應(yīng)該在本文件開(kāi)頭用#include命令將調(diào)用有關(guān)庫(kù)函數(shù)“包含”到本文件中。 如:# include “stdio.h” 在stdio.h文件中放了輸入輸出庫(kù)函數(shù)所用到的一些宏定義信息。 2如果調(diào)用自定義函數(shù),在調(diào)用之前,應(yīng)對(duì)被調(diào)用函數(shù)進(jìn)行說(shuō)明,其目的是:使編譯系統(tǒng)知道被調(diào)用函數(shù)返回值的類(lèi)型、函數(shù)參數(shù)的個(gè)數(shù)、類(lèi)型、和順序,便于調(diào)用時(shí),對(duì)調(diào)用函數(shù)提供的實(shí)際參數(shù)的類(lèi)型、個(gè)數(shù)、及順序進(jìn)行檢查,看是否與被調(diào)用函數(shù)一致。,在ANSI C新標(biāo)準(zhǔn)中,采用函數(shù)原型方式,對(duì)被調(diào)用函數(shù)進(jìn)行說(shuō)明,其一般格式如下: 函數(shù)類(lèi)型 函數(shù)名(數(shù)據(jù)類(lèi)型 參數(shù)名, 數(shù)據(jù)類(lèi)型 參數(shù)名2); 例如:例8.1主函數(shù)中的int max(int n1,int n2);語(yǔ)句,是函數(shù)說(shuō)明語(yǔ)句。說(shuō)明函數(shù)max的返回值類(lèi)型為整型 ,有兩個(gè)形式參數(shù)n1,n2都是整型。 語(yǔ)言同時(shí)又規(guī)定,在以下2種情況下,可以省去對(duì)被調(diào)用函數(shù)的說(shuō)明: (1) 當(dāng)被調(diào)用函數(shù)的函數(shù)定義出現(xiàn)在調(diào)用函數(shù)之前時(shí)。因?yàn)樵谡{(diào)用之前,編譯系統(tǒng)已經(jīng)知道了被調(diào)用函數(shù)的函數(shù)類(lèi)型、參數(shù)個(gè)數(shù)、類(lèi)型和順序。 例8.1 max函數(shù)在主函數(shù)main()之前,主函數(shù)中的int max(int n1,int n2);說(shuō)明語(yǔ)句可以不要。,(2) 如果在所有函數(shù)定義之前,在函數(shù)外部(例如文件開(kāi)始處)預(yù)先對(duì)各個(gè)函數(shù)進(jìn)行了說(shuō)明,則在調(diào)用函數(shù)中可缺省對(duì)被調(diào)用函數(shù)的說(shuō)明。 例如: char f1(int a); /*函數(shù)說(shuō)明*/ float f2(float b); /*函數(shù)說(shuō)明*/ main( ) char f1(int a) /*函數(shù)定義*/ float f2(float b); /*函數(shù)定義*/ ,8.1.4 函數(shù)的調(diào)用,在程序中,是通過(guò)對(duì)函數(shù)的調(diào)用來(lái)執(zhí)行函數(shù)體的,其過(guò)程與其它語(yǔ)言的子程序調(diào)用相似。 1函數(shù)調(diào)用 語(yǔ)言中,函數(shù)調(diào)用的一般形式為: 函數(shù)名(實(shí)際參數(shù)表) (1)實(shí)參的個(gè)數(shù)、類(lèi)型和順序,應(yīng)該與被調(diào)用函數(shù)所要求的參數(shù)個(gè)數(shù)、類(lèi)型和順序一致,才能正確地進(jìn)行數(shù)據(jù)傳遞。 (2)如果實(shí)參有多個(gè),對(duì)實(shí)際參數(shù)的求值順序隨系統(tǒng)而異。Turbo C按自右向左順序求值。,例 8.4 函數(shù)實(shí)際參數(shù)的求值順序。 main() int f(int a, int b); /*函數(shù)說(shuō)明*/ int i=2,p; p=f (i,+i); /*函數(shù)調(diào)用實(shí)參求值順序是從右向左*/ printf(“p=%d“,p); int f(int a, int b) /*a=3 b=3 */ int c; if(ab) c=1; else if(a= =b) c=0; else c=-1; return(c); ,運(yùn)行結(jié)果: p=0,2函數(shù)調(diào)用方式,在語(yǔ)言中,可以用以下幾種方式調(diào)用函數(shù): (1)函數(shù)表達(dá)式。函數(shù)作為表達(dá)式的一項(xiàng),出現(xiàn)在表達(dá)式中,以函數(shù)返回值參與表達(dá)式的運(yùn)算。這種方式要求函數(shù)是有返回值的。 如: c=2*max(a,b); (2)函數(shù)語(yǔ)句。C語(yǔ)言中的函數(shù)可以只進(jìn)行某些操作而不返回函數(shù)值,這時(shí)的函數(shù)調(diào)用可作為一條獨(dú)立的語(yǔ)句。 如:max(a,b); (3)函數(shù)實(shí)參。函數(shù)作為另一個(gè)函數(shù)調(diào)用的實(shí)際參數(shù)出現(xiàn)。這種情況是把該函數(shù)的返回值作為實(shí)參進(jìn)行傳送,因此要求該函數(shù)必須是有返回值的。,如:n=max(a,max(b,c); 其中max(b,c)是一次調(diào)用,它的值作為max另一次調(diào)用的實(shí)參。 (4)調(diào)用時(shí)實(shí)參與形參在類(lèi)型必須匹配。如果類(lèi)型不匹配,C編譯程序?qū)促x值兼容的規(guī)則進(jìn)行轉(zhuǎn)換。(如:實(shí)參實(shí)型a=3.5,而形參x 為整型,則x得到的是3)。如果實(shí)參和形參的類(lèi)型不賦值兼容,通常并不給出出錯(cuò)信息,且程序仍然繼續(xù)執(zhí)行,只是得不到正確的結(jié)果。,8.1.5 函數(shù)的形參與實(shí)參,函數(shù)的參數(shù)分為形參和實(shí)參兩種,作用是實(shí)現(xiàn)數(shù)據(jù)傳送。形參出現(xiàn)在函數(shù)定義中,只能在該函數(shù)體內(nèi)使用。發(fā)生函數(shù)調(diào)用時(shí),調(diào)用函數(shù)把實(shí)參的值復(fù)制1份,傳送給被調(diào)用函數(shù)的形參,從而實(shí)現(xiàn)調(diào)用函數(shù)向被調(diào)用函數(shù)的數(shù)據(jù)傳送。 關(guān)于形參與實(shí)參的說(shuō)明: (1)實(shí)參可以是常量、變量、表達(dá)式、函數(shù)等。無(wú)論實(shí)參是何種類(lèi)型的量,在進(jìn)行函數(shù)調(diào)用時(shí),它們都必須具有確定的值,以便把這些值傳送給形參。因此,應(yīng)預(yù)先用賦值、輸入等辦法,使實(shí)參獲得確定的值。 (2)形參變量只有在被調(diào)用時(shí),才分配內(nèi)存單元;調(diào)用結(jié)束時(shí),即刻釋放所分配的內(nèi)存單元。,因此,形參只有在該函數(shù)內(nèi)有效。調(diào)用結(jié)束,返回調(diào)用函數(shù)后,則不能再使用該形參變量。 (3)實(shí)參對(duì)形參的數(shù)據(jù)傳送是單向的,即只能把實(shí)參的值傳送給形參,而不能把形參的值反向地傳送給實(shí)參。 (4)實(shí)參和形參占用不同的內(nèi)存單元,即使同名也互不影響。如以下程序: 例題8.5 實(shí)參對(duì)形參的數(shù)據(jù)傳遞。 /*功能:實(shí)參對(duì)形參的數(shù)據(jù)傳遞。*/ /*例題源代碼文件名:LT8_5.C*/,main() void s(int n); /*說(shuō)明函數(shù)*/ int n=100; /*定義實(shí)參n,并初始化*/ s(n); /*調(diào)用函數(shù)*/ printf(“n_s=%dn“,n); /*輸出調(diào)用后實(shí)參的值,便于進(jìn)行比較*/ void s(int n) int i; printf(“n_x=%dn“,n); /*輸出改變前形參的值*/ for(i=n-1; i=1; i-) n=n+i; /*改變形參的值*/ printf(“n_x=%dn“,n); /*輸出改變后形參的值*/ ,運(yùn)行結(jié)果: n_x=100 n_x=5050 n_s=100,8.2函數(shù)的嵌套調(diào)用和遞歸調(diào)用,8.2.1函數(shù)的嵌套調(diào)用 函數(shù)的嵌套調(diào)用是指,在執(zhí)行被調(diào)用函數(shù)時(shí),被調(diào)用函數(shù)又調(diào)用了其它函數(shù)。這與其它語(yǔ)言的子程序嵌套調(diào)用的情形是類(lèi)似的,其關(guān)系可表示如圖8-1。,例題8.6計(jì)算s=1k+2k+3k+N k /*例題源代碼文件名:LT8_6.C*/ /*功能:函數(shù)的嵌套調(diào)用*/ #define K 4 #define N 5 long f1(int n,int k) /*計(jì)算n的k次方*/ long power=n; int i; for(i=1;ik;i+) power *= n; return power; ,long f2 (int n,int k) /*計(jì)算1到n的k次方之累加和*/ long sum=0; int i; for(i=1;i=n;i+) sum += f1(i, k); return sum; main() printf(“Sum of %d powers of integers from 1 to %d = “,K,N); printf(“%dn“,f2(N,K); getch(); ,本程序編寫(xiě)了兩個(gè)函數(shù):一個(gè)用來(lái)計(jì)算n的函數(shù)f1(),另一個(gè)計(jì)算累加和的函數(shù)f2()。主函數(shù)先調(diào)用f2()計(jì)算累加和,再在f2()中調(diào)用f1()。f1()和f2()均為長(zhǎng)整型,都在主函數(shù)之前定義,故不必再在主函數(shù)中對(duì)f1()和f2()加以說(shuō)明。由于計(jì)算數(shù)值會(huì)很大,所以函數(shù)和一些變量的類(lèi)型都說(shuō)明為長(zhǎng)整型。,8.2.2 函數(shù)的遞歸調(diào)用 函數(shù)的遞歸調(diào)用是指,一個(gè)函數(shù)在它的函數(shù)體內(nèi),直接或間接地調(diào)用它自身。,例8.7 用遞歸法計(jì)算n!。 用遞歸法計(jì)算n!,可以用下面公式表示: 1 (n=1) n!= n*(n-1)! (n1) /*例題源代碼文件名:LT8_7.C*/*功能:通過(guò)函數(shù)的遞歸調(diào)用計(jì)算階乘*/ long p(int n) long f; if(n1) f=p(n-1)*n; else f=1; return(f); ,main() int n; long y; printf(“input a inteager number: “); scanf(“%d“, ,運(yùn)行結(jié)果: input a inteager number:5 5!=120,例題8.8 填空題:以下程序的輸出結(jié)果是:_ /*例題源代碼文件名:LT8_8.C*/ func(int x) int p; if(x= =0|x= =1) return(3); p=x-func(x-2); return p; main( ) printf(“%dn”,func(9); ,分析:,所以程序的輸出結(jié)果是:7,8.3 數(shù)組作為函數(shù)參數(shù),數(shù)組用作函數(shù)參數(shù)有兩種形式:一種是把數(shù)組元素(又稱(chēng)下標(biāo)變量)作為實(shí)參使用; 另一種是把數(shù)組名作為函數(shù)的形參和實(shí)參使用。 8.3.1 數(shù)組元素作為函數(shù)參數(shù) 數(shù)組元素就是下標(biāo)變量,它與普通變量并無(wú)區(qū)別。數(shù)組元素只能用作函數(shù)實(shí)參,其用法與普通變量完全相同:在發(fā)生函數(shù)調(diào)用時(shí),把數(shù)組元素的值傳送給形參,實(shí)現(xiàn)單向值傳送。,例題8.9寫(xiě)一函數(shù)統(tǒng)計(jì)字符串中字母的個(gè)數(shù)。 /*例題源代碼文件名:LT8_9.C*/ /*功能:數(shù)組元素作為函數(shù)實(shí)參*/ int isalp(char c) if (c=a ,main() int i,num=0; char str255; printf(“Input a string: “); gets(str); for(i=0;stri!=0;i+) if (isalp(stri) num+; /*數(shù)組元素作為實(shí)際參數(shù)調(diào)用函數(shù)*/ puts(str); /*輸出字符串*/ printf(“num=%dn“,num); /*輸出字母?jìng)€(gè)數(shù)*/ ,運(yùn)行結(jié)果: Input a string: We study Turbo C! We study Turbo C! num=13,本例題子函數(shù)功能判斷一個(gè)字符是否為字母,是返回值為1,否則為0。主函數(shù)調(diào)用時(shí)用語(yǔ)句for(i=0;stri!=0;i+) if (isalp(stri) num+; isalp(stri)返回值為1,表示是真,用num+統(tǒng)計(jì)字母的個(gè)數(shù),isalp(stri)返回值為0,則什么也不做。 說(shuō)明: (1)用數(shù)組元素作實(shí)參時(shí),只要數(shù)組類(lèi)型和函數(shù)的形參類(lèi)型一致即可,并不要求函數(shù)的形參也是下標(biāo)變量。換句話說(shuō),對(duì)數(shù)組元素的處理是按普通變量對(duì)待的。 (2)在普通變量或下標(biāo)變量作函數(shù)參數(shù)時(shí),形參變量和實(shí)參變量是由編譯系統(tǒng)分配的兩個(gè)不同的內(nèi)存單元。在函數(shù)調(diào)用時(shí)發(fā)生的值傳送,是把實(shí)參變量的值賦予形參變量。,8.3.2 數(shù)組名作為函數(shù)的形參和實(shí)參,數(shù)組名作函數(shù)參數(shù)時(shí),既可以作形參,也可以作實(shí)參。 數(shù)組名作函數(shù)參數(shù)時(shí),要求形參和相對(duì)應(yīng)的實(shí)參都必須是類(lèi)型相同的數(shù)組(或指向數(shù)組的指針變量),都必須有明確的數(shù)組說(shuō)明。 例題8.10已知某個(gè)學(xué)生5門(mén)課程的成績(jī),求平均成績(jī)。 /*例題源代碼文件名:LT8_10.C*/ float aver(float a ) /*求平均值函數(shù)*/ int i; float av,sum=a0; for(i=1;i5;i+) sum += ai; av=sum/5; return av; ,void main() float s5,av; int i; printf(“ninput 5 scores:n“); for(i=0;i5;i+) scanf(“%f“, ,運(yùn)行結(jié)果: input 5 scores: 80 70 65 90 75 average score is 76.00,說(shuō)明: (1)用數(shù)組名作函數(shù)參數(shù),應(yīng)該在調(diào)用函數(shù)和被調(diào)用函數(shù)中分別定義數(shù)組,且數(shù)據(jù)類(lèi)型必須一致,否則結(jié)果將出錯(cuò)。例如,在本案例中,形參數(shù)組為a ,實(shí)參數(shù)組為s ,它們的數(shù)據(jù)類(lèi)型相同。(形參數(shù)組與實(shí)參數(shù)組可以同名) (2)C編譯系統(tǒng)對(duì)形參數(shù)組大小不作檢查,所以形參數(shù)組可以不指定大小。例如,本案例中的形參數(shù)組a 。 為了在被調(diào)用函數(shù)中處理數(shù)組元素的需要,可以另設(shè)一個(gè)參數(shù),傳遞數(shù)組元素的個(gè)數(shù)。 例如:將上例中的aver( ) 改進(jìn)為如下:,例題8.11 float aver(float a ,int n) /*求平均值函數(shù)*/ int i; float av,sum=a0; for(i=1;in;i+) sum += ai; av=sum/n; return av; main() float s15=98.5,97,91.5,60,55; float s210=98,85,75,70,60,65,77,88,90,66; printf(“aver1=%6.2fn”,aver(s1,5); /*調(diào)用函數(shù),實(shí)參為一數(shù)組名s1*/ printf(“aver2=%6.2fn”,aver(s2,10); ,運(yùn)行結(jié)果: aver1=80.40 aver2=77.4,可以看出,兩次調(diào)用aver( )函數(shù)時(shí)數(shù)組大小是不同的,在調(diào)用時(shí)用一個(gè)實(shí)參傳遞數(shù)組大小給形參n,以便aver( )函數(shù)能處理數(shù)組大小不同的數(shù)組元素。 如果指定形參數(shù)組的大小,則實(shí)參數(shù)組的大小必須大于等于形參數(shù)組,否則因形參數(shù)組的部分元素沒(méi)有確定值而導(dǎo)致計(jì)算結(jié)果錯(cuò)誤。,(3)數(shù)組名作為參數(shù),只是將實(shí)參數(shù)組的首地址傳給形參數(shù)組,從而使形參數(shù)組與實(shí)參數(shù)組共用同一段內(nèi)存空間。假設(shè)s1數(shù)組的起始地址為1000,則a數(shù)組的起始地址也是1000 顯然形參數(shù)組和實(shí)參數(shù)組為同一數(shù)組。s0與a0同占一個(gè)單元。所以如果形參數(shù)組元素的值發(fā)生變化,也就是實(shí)參數(shù)組元素發(fā)生變化。這種數(shù)據(jù)傳遞方式稱(chēng)為“地址傳遞”。,8.4 函數(shù)編程舉例,1編程舉例 例8.12編程求sum=1+1/2+1/3+1/4+1/5+1/n /*例題源代碼文件名:LT8_12.C*/ # include “stdio.h” main( ) double fun(int n); /*函數(shù)的說(shuō)明,注意末尾要加;*/ int n; scanf(“%d”,int i; for(i=1;i=n;i+) sum+=1.0/i; return (sum); 注意: 本例計(jì)算1+1/2+1/31/n.由于“/”除號(hào)當(dāng)除數(shù)和被除數(shù)均為整型時(shí),商為整數(shù),1/2=0、1/3=0所以要這樣寫(xiě)sum+=1.0/i; 被除數(shù)是實(shí)型1.0除數(shù)是整型作“/”除法sum才能得到實(shí)數(shù)各項(xiàng)和。,運(yùn)行時(shí)輸入10 輸出結(jié)果為: sum=2.928968,2閱讀程序訓(xùn)練,例8.13 以下程序運(yùn)行結(jié)果是_10,20_. func(int a,int b) int temp; temp=a; a=b; b=temp; main( ) int x,y; x=10;y=20; func(x,y); printf(“%d,%dn”,x,y); (a) 10,20 (b) 10,10 (c) 20,10 (d) 20,20,答案: (a),解析: 這里是實(shí)參x,y向形參a,b值傳遞,在函數(shù)中只將形參a,b的值 交換。不會(huì)改變實(shí)參的值,所以輸出x,y的值仍為10,20。,例題8.14以下程序運(yùn)行結(jié)果是_0 2 4 6_. /*例題源代碼文件名:LT8_14.C*/ void f1(int b ) int j; for(j=0;j4;j+) bj=2*j; main( ) int a =5,6,7,8,i; f1(a); for(i=0;i4;i+) printf(“%dt”,ai); ,解析: 本題是數(shù)組名作為實(shí)際參數(shù)進(jìn)行調(diào)用,只是將實(shí)參數(shù)組a的首地址傳給形參數(shù)組b,從而使形參數(shù)組與實(shí)參數(shù)組共用同一段內(nèi)存空間。即數(shù)組b就是數(shù)組a,所以形參數(shù)組b的變化就是a數(shù)組的變化,所以在主函數(shù)中的printf(“%dt”,ai);語(yǔ)句,輸出0 2 4 6。這里的t是轉(zhuǎn)義字符表示橫向跳到下一個(gè)輸出區(qū),使用它為了隔開(kāi)每一個(gè)數(shù)據(jù)。,8.5 內(nèi)部變量與外部變量,語(yǔ)言中所有的變量都有自己的作用域。變量說(shuō)明的位置不同,其作用域也不同,據(jù)此將語(yǔ)言中的變量分為內(nèi)部變量和外部變量。 8.5.1內(nèi)部變量 在一個(gè)函數(shù)內(nèi)部定義的變量是內(nèi)部變量,它只在該函數(shù)范圍內(nèi)有效。也就是說(shuō),只有在本函數(shù)內(nèi)部才能使用它們,在此函數(shù)之外就不能使用這些變量了。所以內(nèi)部變量也稱(chēng)“局部變量”。,例如: int f1(int a) /*函數(shù)f1*/ int b,c; /*a,b,c作用域:僅限于函數(shù)f1()中*/ int f2(int x) /*函數(shù)f2*/ int y,z; /*x,y,z作用域:僅限于函數(shù)f2()中*/ main() int m,n; /*m,n作用域:僅限于函數(shù)main()中*/,關(guān)于內(nèi)部變量的作用域還要說(shuō)明以下幾點(diǎn):,1主函數(shù)main()中定義的內(nèi)部變量,也只能在主函數(shù)中使用,其它函數(shù)不能使用。同時(shí),主函數(shù)中也不能使用其它函數(shù)中定義的內(nèi)部變量。因?yàn)橹骱瘮?shù)也是一個(gè)函數(shù),與其它函數(shù)是平行關(guān)系。這一點(diǎn)是與其它語(yǔ)言不同的,應(yīng)予以注意。 2形參變量也是內(nèi)部變量,屬于被調(diào)用函數(shù);實(shí)參變量,則是調(diào)用函數(shù)的內(nèi)部變量。 3允許在不同的函數(shù)中使用相同的變量名,它們代表不同的對(duì)象,分配不同的單元,互不干擾,也不會(huì)發(fā)生混淆。 4在復(fù)合語(yǔ)句中也可定義變量,其作用域只在復(fù)合語(yǔ)句范圍內(nèi) main( ) int a,b; . int c; /*c是在復(fù)合語(yǔ)句中定義的變量因此在復(fù)合語(yǔ)句范圍內(nèi)有效*/ c=a+b; ,8.5.2 外部變量,在函數(shù)外部定義的變量稱(chēng)為外部變量。外部變量不屬于任何一個(gè)函數(shù),其作用域是:從外部變量的定義位置開(kāi)始,到本文件結(jié)束為止。外部變量可被作用域內(nèi)的所有函數(shù)直接引用,所以外部變量又稱(chēng)全局變量。 如: int a=1,b=5; float f1(int x) int c,d; ,char c1,c2; char f2(int x,int y) int i,j; main( ) int m,n; ,對(duì)于外部變量還有以下幾點(diǎn)說(shuō)明: 1. 外部變量可加強(qiáng)函數(shù)模塊之間的數(shù)據(jù)聯(lián)系。由于同一文件中的所有函數(shù)都可以引用外部變量的值,因此,如果在一個(gè)函數(shù)中改變了外部變量的值,就能影響到其他函數(shù),相當(dāng)于各函數(shù)間有直接的傳遞通道。由于函數(shù)的調(diào)用只能帶回一個(gè)返回值,因此有時(shí)可以利用外部變量與函數(shù)聯(lián)系的渠道,從函數(shù)得到一個(gè)以上的返回值。,例題8.15 輸入長(zhǎng)方體的長(zhǎng)(l)、寬(w)、高(h),求長(zhǎng)方體體積及正、側(cè)、頂三個(gè)面的面積。 /*例題源代碼文件名:LT8_15.C*/。 /*功能:利用外部變量計(jì)算長(zhǎng)方體的體積及三個(gè)面的面積*/ int s1,s2,s3; int vs(int a,int b,int c) int v; v=a*b*c; s1=a*b; s2=b*c; s3=a*c; return v; ,main() int v,l,w,h; clrscr(); printf(“ninput length,width and height: “); scanf(“%d%d%d“, ,運(yùn)行結(jié)果: input length,width and height:3 4 5 v=60 s1=12 s2=20 s3=15,本例程序的開(kāi)頭,定義了三個(gè)外部變量s1,s2,s3,存放長(zhǎng)方體的正、側(cè)、頂三個(gè)面的面積。其作用域是從開(kāi)頭到文件末尾,所以在主函數(shù)中仍有效,相當(dāng)于把在子函數(shù)中的計(jì)算值帶回主函數(shù)。長(zhǎng)方體的體積v用return v;語(yǔ)句返回體積值。這樣達(dá)到從子函數(shù)返回了一個(gè)以上的值。 但是,以上方法雖然外部變量加強(qiáng)了函數(shù)模塊之間的數(shù)據(jù)聯(lián)系,但又使這些函數(shù)依賴這些外部變量,因而使得這些函數(shù)的獨(dú)立性降低。從模塊化程序設(shè)計(jì)的觀點(diǎn)來(lái)看這是不利的,因?yàn)樵诔绦蛟O(shè)計(jì)中,模塊的功能要單一,,與其他模塊的互相影響要盡量少,而用外部變量是不符合這個(gè)原則的。一般要求把c程序中的函數(shù)做成一個(gè)封閉體,除了可以通過(guò)“實(shí)參和形參“的渠道與外界發(fā)生聯(lián)系外,沒(méi)有其他渠道。這樣的程序移值性好,可讀性強(qiáng)。因此不是非用不可時(shí),不要使用外部變量。 2. 在同一源文件中,允許外部變量和內(nèi)部變量同名。在內(nèi)部變量的作用域內(nèi),外部變量將被屏蔽而不起作用。 例題8.16外部變量與內(nèi)部變量同名 /*例題源代碼文件名:LT8_16.C*/,int a=3,b=5; /*a,b是外部變量*/ max( int a,int b) /*a,b是函數(shù)的形參為內(nèi)部變量*/ int c; c=ab?a:b; return (c); main( ) int a=8; /*a為主函數(shù)的內(nèi)部變量*/ printf(“%d”,max(a,b); ,運(yùn)行結(jié)果: 8,本例在主函數(shù)中調(diào)用時(shí),max(a,b)中,a是主函數(shù)的內(nèi)部變量起作用,外部變量a將被屏蔽而不起作用。因此a=8 b=5進(jìn)行調(diào)用,結(jié)果返回8。 3. 外部變量的作用域是從定義點(diǎn)到本文件結(jié)束。如果本文件定義點(diǎn)之前的函數(shù)需要引用這些外部變量或在其他文件中要引用時(shí),需要用extern來(lái)聲明外部變量,以擴(kuò)展外部變量的作用域。 外部變量說(shuō)明的一般形式為: extern 數(shù)據(jù)類(lèi)型 外部變量,外部變量2;,在一個(gè)文件內(nèi)聲明外部變量 如果外部變量不在文件的開(kāi)頭定義,其有效的作用范圍只限于定義處到文件末尾。如果本文件定義點(diǎn)之前的函數(shù)需要引用這些外部變量,則如下例方法進(jìn)行引用。 例題8.17用extern聲明外部變量,擴(kuò)展程序文件中的作用域。 /*例題源代碼文件名:LT8_17.C*/,int max(int x,int y) int z; z=xy ? x :y ; return (z); main( ) extern a,b; /*在引用前外部變量聲明*/ printf(“%d”,max(a,b);/*引用外部變量*/ int a=13,b=-8; /*定義外部變量在后*/,運(yùn)行結(jié)果: 13,(2)在多個(gè)文件的程序中聲明外部變量 在一個(gè)文件中定義外部變量,而另一個(gè)文件中用extern進(jìn)行聲明 。 例題8.18用extern將外部變量的作用域擴(kuò)展到其他文件。 文件LT8_18a.C的內(nèi)容: int a; main( ) int b,c,m=3; scanf(“%d%d”, ,文件LT8_18b.C的內(nèi)容: extern a; /*聲明本文件LT8_18b.C中的a是一個(gè)已經(jīng)在其他文件中定義過(guò)的外部變量*/ fun(int n) int y; y=a+n; retirn (y); 用以上方法應(yīng)十分慎重,因?yàn)樵趫?zhí)行一個(gè)文件中的函數(shù)時(shí),可能會(huì)改變?cè)撏獠孔兞康闹?,它?huì)影響到另一個(gè)文件的函數(shù)執(zhí)行結(jié)果。,4在定義外部變量時(shí)加static,則外部變量只限于被本文件引用,而不能被其他文件引用。 文件file1.c的內(nèi)容: static int a; main() 則a變量只能在文件file1.c中使用。(定義是不加static就可以用extern擴(kuò)展其作用域范圍。如前面第3點(diǎn)所說(shuō)),8.6 變量的存儲(chǔ)類(lèi)別,8.6.1動(dòng)態(tài)存儲(chǔ)方式和靜態(tài)存儲(chǔ)方式 上一節(jié)從變量的作用域(即從空間)角度來(lái)分,分為:內(nèi)部變量和外部變量。 從另一角度,從變量值存在的時(shí)間(即生存期)角度來(lái)分,可分為:動(dòng)態(tài)存儲(chǔ)方式和靜態(tài)存儲(chǔ)方式。 所謂靜態(tài)存儲(chǔ)方式是指在程序運(yùn)行期間分配固定的存儲(chǔ)空間的方式。而動(dòng)態(tài)存儲(chǔ)方式則是在程序運(yùn)行期間根據(jù)需要進(jìn)行動(dòng)態(tài)的分配存儲(chǔ)空間的方式。 內(nèi)存中供用戶使用的存儲(chǔ)空間情況如圖8-5 1.程序區(qū) 2.靜態(tài)存儲(chǔ)區(qū) 3.動(dòng)態(tài)存儲(chǔ)區(qū),靜態(tài)存儲(chǔ)區(qū)存放外部變量。 動(dòng)態(tài)存儲(chǔ)區(qū)存放以下數(shù)據(jù): 函數(shù)的形參。在調(diào)用函數(shù)時(shí)給形參分配存儲(chǔ)空間。 未加static聲明的內(nèi)部變量(即自動(dòng)變量,后面介紹) 函數(shù)調(diào)用時(shí)的現(xiàn)場(chǎng)保護(hù)和返回地址。 8.6.2自動(dòng)變量 函數(shù)中的內(nèi)部變量,如果定義時(shí)不加static,就是自動(dòng)變量。是動(dòng)態(tài)分配存儲(chǔ)空間的。函數(shù)的形參和在函數(shù)中定義的變量,都屬于此類(lèi)。在調(diào)用該函數(shù)時(shí)系統(tǒng)會(huì)給它們分配存儲(chǔ)空間,在函數(shù)調(diào)用結(jié)束就自動(dòng)釋放這些存儲(chǔ)空間。自動(dòng)變量用關(guān)鍵字auto作存儲(chǔ)類(lèi)別的聲明。,例如: int f(int a) auto int b,c=3; a是形參,b,c是自動(dòng)變量,執(zhí)行完f函數(shù)后,自動(dòng)釋放a,b,c所占的存儲(chǔ)空間。關(guān)鍵字”auto”可以省略。不寫(xiě)auto 隱含表示是自動(dòng)變量。 auto int b,c; 和int b,c;是等價(jià)的 關(guān)于自動(dòng)變量的說(shuō)明: 1自動(dòng)變量屬于動(dòng)態(tài)存儲(chǔ)方式。在函數(shù)中定義的自動(dòng)變量,只在該函數(shù)內(nèi)有效;函數(shù)被調(diào)用時(shí)分配存儲(chǔ)空間,調(diào)用結(jié)束就釋放。,在復(fù)合語(yǔ)句中定義的自動(dòng)變量,只在該復(fù)合語(yǔ)句中有效;退出復(fù)合語(yǔ)句后,也不能再使用,否則將引起錯(cuò)誤。 2定義而不初始化,則其值是不確定的。如果初始化,則賦初值操作是在調(diào)用時(shí)進(jìn)行的,且每次調(diào)用都要重新賦一次初值。 3由于自動(dòng)變量的作用域和生存期,都局限于定義它的個(gè)體內(nèi)(函數(shù)或復(fù)合語(yǔ)句),因此不同的個(gè)體中允許使用同名的變量而不會(huì)混淆。即使在函數(shù)內(nèi)定義的自動(dòng)變量,也可與該函數(shù)內(nèi)部的復(fù)合語(yǔ)句中定義的自動(dòng)變量同名。,8.6.3用static聲明的內(nèi)部變量,有時(shí)希望函數(shù)中的內(nèi)部變量的值在函數(shù)調(diào)用結(jié)束后不消失而保留原值,在下一次調(diào)用該函數(shù)時(shí),該變量已有值,就是上一次函數(shù)調(diào)用結(jié)束的值。這時(shí)用“靜態(tài)內(nèi)部變量”。 1定義靜態(tài)內(nèi)部變量方式: static 數(shù)據(jù)類(lèi)型 內(nèi)部變量表; 存儲(chǔ)特點(diǎn): (1)靜態(tài)內(nèi)部變量屬于靜態(tài)存儲(chǔ)。在程序執(zhí)行過(guò)程中,即使所在函數(shù)調(diào)用結(jié)束也不釋放。換句話說(shuō),在程序執(zhí)行期間,靜態(tài)內(nèi)部變量始終存在,但其它函數(shù)是不能引用它們的,只能本函數(shù)引用。 (2)定義但不初始化,則自動(dòng)賦以“(整型和實(shí)型)或0(字符型);,(3)對(duì)靜態(tài)內(nèi)部變量是在編譯時(shí)賦初值的,即只賦初值一次,在程序運(yùn)行時(shí),它已有初值。以后每次調(diào)用它們所在的函數(shù)時(shí),不再重新賦初值而只是保留上次函數(shù)調(diào)用結(jié)束時(shí)的值。 例題8.19靜態(tài)內(nèi)部變量的使用。 /*例題源代碼文件名:LT8_19.C*/ f(int a) auto int b=0; /*動(dòng)態(tài)內(nèi)部變量(自動(dòng)變量)*/ static int c=3; /*靜態(tài)內(nèi)部變量*/ b=b+1;,c=c+1; return (a+b+c); main( ) int a=2,x; for(x=0;x3;x+) printf(“%d”,f(a); ,運(yùn)行結(jié)果: 7 8 9,例題8.19調(diào)用過(guò)程各變量值列表,8.6.4寄存器變量register,一般情況下,變量的值都是存儲(chǔ)在內(nèi)存中的。為提高執(zhí)行效率,語(yǔ)言允許將局部變量的值存放到寄存器中,這種變量就稱(chēng)為寄存器變量。(寄存器存取速度快) 定義格式如下: register 數(shù)據(jù)類(lèi)型 變量表; (1)只有局部動(dòng)態(tài)變量和形參才能定義成寄存器變量,即全局變量不行。 (2)對(duì)寄存器變量的實(shí)際處理,隨系統(tǒng)而異。例如,微機(jī)上的MSC和TC 將寄存器變量實(shí)際當(dāng)作自動(dòng)變量處理。 (3)允許使用的寄存器數(shù)目是有限的,不能定義任意多個(gè)寄存器變量。 (4)局部靜態(tài)變量不能定義為寄存器變量。,8.7 內(nèi)部函數(shù)和外部函數(shù),當(dāng)一個(gè)源程序由多個(gè)源文件組成時(shí),語(yǔ)言根據(jù)函數(shù)能否被其它源文件中的函數(shù)調(diào)用,將函數(shù)分為內(nèi)部函數(shù)和外部函數(shù)。 8.7.1 內(nèi)部函數(shù)(又稱(chēng)靜態(tài)函數(shù)) 如果在一個(gè)源文件中定義的函數(shù),只能被本文件中的函數(shù)調(diào)用,而不能被同一程序其它文件中的函數(shù)調(diào)用,這種函數(shù)稱(chēng)為內(nèi)部函數(shù)。 定義一個(gè)內(nèi)部函數(shù),只需在函數(shù)類(lèi)型前再加一個(gè)“static”關(guān)鍵字即可,如下所示: static 函數(shù)類(lèi)型 函數(shù)名(函數(shù)參數(shù)表) 關(guān)鍵字“static”,譯成中文就是“靜態(tài)的”,所以內(nèi)部函數(shù)又稱(chēng)靜態(tài)函數(shù)。但此處“static”的含義不是指存儲(chǔ)方式,而是指對(duì)函數(shù)的作用域僅局限于本文件。,8.7.2 外部函數(shù),如果在一個(gè)源文件中定義的函數(shù),除可被本文件中的其他函數(shù)調(diào)用外,也可被其他文件中的函數(shù)所調(diào)用,這種函數(shù)稱(chēng)為外部函數(shù)。外部函數(shù)在整個(gè)源程序中都有效。 外部函數(shù)的定義:在定義函數(shù)時(shí),如果沒(méi)有加關(guān)鍵字“static”,或冠以關(guān)鍵字“extern”,表示此函數(shù)是外部函數(shù): extern 函數(shù)類(lèi)型 函數(shù)名(函數(shù)參數(shù)表) 調(diào)用外部函數(shù)時(shí),需要對(duì)其進(jìn)行說(shuō)明: extern 函數(shù)類(lèi)型 函數(shù)名(參數(shù)類(lèi)型表),函數(shù)名2(參數(shù)類(lèi)型表2);,如: 外部函數(shù)應(yīng)用,(1)文件mainf.c main() extern void input(),process(),output(); /*對(duì)外部函數(shù)進(jìn)行說(shuō)明*/ input(); process(); output(); /*調(diào)用外部函數(shù)*/ (2)文件subf1.c extern void input() /*定義外部函數(shù)*/ (3)文件subf2.c extern void process() /*定義外部函數(shù)*/ (4)文件subf3.c extern void output() /*定義外部函數(shù)*/ ,8.7.3 多個(gè)源程序文件的編譯和連接,1、用Turbo C集成環(huán)境(以上面4個(gè)文件組成的程序?yàn)槔?(1)先后分別輸入并編輯文件mainf.c, 文件subf1.c, 文件subf2.c, 文件subf3.c存盤(pán)。 (2)創(chuàng)建Project(項(xiàng)目)文件: 用編輯源文件相同的方法,創(chuàng)建一個(gè)擴(kuò)展名為.PRJ的項(xiàng)目文件,該文件中僅包括將被編譯、連接的各源文件名,一行一個(gè),其擴(kuò)展名.C可以缺省;文件名的順序,僅影響編譯的順序,與運(yùn)行無(wú)關(guān)。 項(xiàng)目文件的內(nèi)容為: mainf.c subf1.c subf2.c subf3.c,(3)設(shè)置項(xiàng)目名稱(chēng): 打開(kāi)菜單,選取Project菜單選Project name項(xiàng)按回車(chē),屏幕出現(xiàn)一個(gè)對(duì)話框,詢問(wèn)項(xiàng)目文件名,輸入項(xiàng)目文件名a.prj, 其作用是表示當(dāng)前準(zhǔn)備編譯的是a.prj中包括的文件。 (4)按功能鍵F9進(jìn)行編譯、連接,系統(tǒng)先后將4個(gè)文件翻譯成目標(biāo)文件,并把它們連接成一個(gè)可執(zhí)行文件a.exe。 (5)按ctrl+F9運(yùn)行可執(zhí)行文件a.exe。 與單個(gè)源文件相同。編譯產(chǎn)生的目標(biāo)文件,以及連接產(chǎn)生的可執(zhí)行文件,它們的主文件名,均與項(xiàng)目文件的主文件名相同。 注意:當(dāng)前項(xiàng)目文件調(diào)試完畢后,應(yīng)選取ProjectClear project,將其項(xiàng)目名稱(chēng)從“Project name”中清除(清除后為空)。否則,編譯、連接和運(yùn)行的,始終是該項(xiàng)目文件!,8.8編譯預(yù)處理,所謂編譯預(yù)處理是指在對(duì)源程序進(jìn)行編譯之前,先對(duì)源程序中的編譯預(yù)處理命令進(jìn)行處理;然后再將處理的結(jié)果,和源程序一起進(jìn)行編譯,以得到目標(biāo)代碼。 編譯預(yù)處理是C語(yǔ)言的一個(gè)重要功能,由編譯預(yù)處理程序完成。為了與 C語(yǔ)言語(yǔ)句區(qū)別開(kāi),編譯預(yù)處理命令以#號(hào)打頭,單獨(dú)占用一個(gè)書(shū)寫(xiě)行,行尾不使用分號(hào)作為結(jié)束符。,8.8.1 宏定義與宏展開(kāi),在語(yǔ)言中,“宏”分為無(wú)參數(shù)的宏(簡(jiǎn)稱(chēng)無(wú)參宏)和有參數(shù)的宏(簡(jiǎn)稱(chēng)有參宏)兩種。 1無(wú)參宏定義 (1)無(wú)參宏定義的一般格式 #define 標(biāo)識(shí)符 語(yǔ)言符號(hào)字符串 其中:“define”為宏定義命令;“標(biāo)識(shí)符”為所定義的宏名,通常用大寫(xiě)字母表示,以便于與變量區(qū)別;“語(yǔ)言符號(hào)字符串”可以是常數(shù)、表達(dá)式等。,例題8.20輸入圓的半徑,求圓的周長(zhǎng)、面積和球的體積。要求使用無(wú)參宏定義圓周率。,#define PI 3.1415926 /*PI是宏名,3.1415926用來(lái)替換宏名的常數(shù)*/ main() float r,len,s,v; printf(“Input a radius: “); scanf(“%f“, ,編譯預(yù)處理后,宏展開(kāi)的結(jié)果如下: len=2*3.1415926*r; s=3.1415926*r*r; /*用3.1415926替換宏名PI*/ v=3.1415926*r*r*r*3/4; ,(2)說(shuō)明,宏名一般用大寫(xiě)字母表示,以示與變量區(qū)別。但這并非是規(guī)定。 宏定義不是語(yǔ)句,所以不能在行尾加分號(hào)。否則,宏展開(kāi)時(shí),會(huì)將分號(hào)作為字符串的1個(gè)字符,用于替換宏名。 宏展開(kāi)時(shí),預(yù)處理程序僅以按宏定義簡(jiǎn)單替換宏名,而不作任何檢查。如果有錯(cuò)誤,只能由編譯程序在編譯宏展開(kāi)后的源程序時(shí)發(fā)現(xiàn)。 如:# define PI 3.I4I59 把數(shù)字1寫(xiě)成字母I,預(yù)處理時(shí)也照樣代入,不管含義是否正確,不作任何檢查。 宏定義命令#define出現(xiàn)在函數(shù)的外部,宏名的有效范圍是:從定義命令之后, 到本文件結(jié)束。通常,宏定義命令放在文件開(kāi)頭處。 如果需要,也可以#undef命令終止宏名的作用域。如:,#define PI 3.1415926 main( ) #undef PI /*終止宏名PI的作用域,即PI只在main( )函數(shù)中有效*/ void fun() 在進(jìn)行宏定義時(shí),可以引用已定義的宏名 。 #define PI 3.1415926 #define R 2.5 #define LEN 2*PI*R /*引用已定義的宏名PI 和R*/ ,對(duì)雙引號(hào)括起來(lái)的字符串內(nèi)的字符,即使與宏名同名,也不進(jìn)行宏展開(kāi)。 #define PI 3.14 main( ) printf(“PI=%.2fn”,PI); 運(yùn)行結(jié)果: PI=3.14 使用宏名代替一個(gè)字符串,可以減少程序中重復(fù)書(shū)寫(xiě)某些字符串的工作量。如:如果不定義PI代表3.1415926,則在程序中要多處出現(xiàn)3.1415926,不僅麻煩,而且容易寫(xiě)錯(cuò),用宏名代替,簡(jiǎn)單不易出錯(cuò)。另外當(dāng)需要改變某一個(gè)常量時(shí),可以只改變#define命令行,一改全改。,宏定義是專(zhuān)門(mén)用于預(yù)處理命令的一個(gè)專(zhuān)用名詞,它與定義變量的含義不同,只作字符替換,不分配內(nèi)存空間。 2有參宏定義 帶參宏定義的一般格式 #define 宏名(形參表) 語(yǔ)言符號(hào)字符串 帶參宏的調(diào)用和宏展開(kāi) (1)調(diào)用格式:宏名(實(shí)參表) (2)宏展開(kāi):用宏調(diào)用提供的實(shí)參字符串,直接置換宏定義命令行中、相應(yīng)形參字符串,非形參字符保持不變。 #define S(a,b) a*b area=S(3,2);是宏展開(kāi),展開(kāi)后為:area=3*2;,說(shuō)明: 定義有參宏時(shí),宏名與左圓括號(hào)之間不能留有空格。否則,編譯系統(tǒng)將空格以后的所有字符均作為替代字符串,而將該宏視為無(wú)參宏。 有參宏的展開(kāi),只是將實(shí)參作為字符串,簡(jiǎn)單地置換形參字符串,而不做任何語(yǔ)法檢查。在定義有參宏時(shí),在所有形參外和整個(gè)字符串外,均加一對(duì)圓括號(hào)。 例題8.21 /*例題源代碼文件名:LT8_21.C*/ #define PI 3.14 #define S(r) PI*r*r,main( ) float a,b,area; a=3.5; b=2.5; area=S(a+b); printf(“area=%fn”,area); 運(yùn)行結(jié)果: area=22.240000 宏展開(kāi)后為:area=PI*a+b*a+b;,請(qǐng)注意:在a+b外面沒(méi)有括號(hào),顯然這與程序設(shè)計(jì)者的原意不符合。原意希望得到 area=PI*(a+b)*(a+b); 為了得到這個(gè)結(jié)果,應(yīng)該在定義時(shí),在字符串中的形式參數(shù)外面加一個(gè)括號(hào)。即 #definr S(R) PI*(r)* (r) 雖然有參宏與有參函數(shù)確實(shí)有相似之處,但不同之處更多,主要有以下幾個(gè)方面: 調(diào)用有參函數(shù)時(shí),是先求出實(shí)參的值,然后再?gòu)?fù)制一份給形參。而展開(kāi)有參宏時(shí),只是將實(shí)參簡(jiǎn)單地置換形參。 在有參函數(shù)中,形參是有類(lèi)型的,所以要求實(shí)參的類(lèi)型與其一致;而在有參宏中,形參是沒(méi)有類(lèi)型信息的,因此用于置換的實(shí)參,什么類(lèi)型都可以。有時(shí),可利用有參宏的這一特性,實(shí)現(xiàn)通用函數(shù)功能。,使用有參函數(shù),無(wú)論調(diào)用多少次,都不會(huì)使目標(biāo)程序變長(zhǎng),但每次調(diào)用都要占用系統(tǒng)時(shí)間進(jìn)行調(diào)用現(xiàn)場(chǎng)保護(hù)和現(xiàn)場(chǎng)恢復(fù);而使用有參宏,由于宏展開(kāi)是在編譯時(shí)進(jìn)行的,所以不占運(yùn)行時(shí)間,但是引用時(shí),會(huì)使目標(biāo)程序增大。 3閱讀程序練習(xí): 例8.22以下程序的運(yùn)行結(jié)果是_15_ /*例題源代碼文件名:LT8_22.C*/ # define MIN(x,y) (x)(y)?(x):(y) main( ) int a,b,c; a=10;,b=15; c=10*MIN(a,b); printf(“%d”,c); 解析:因?yàn)橛袇⒑暾归_(kāi),只是將實(shí)參作為字符串,簡(jiǎn)單地置換形參字符串,展開(kāi)后為: c=10*(10)(15)?(10):(15);然后編譯、連接、執(zhí)行,由于*乘法運(yùn)算優(yōu)先級(jí)高于條件運(yùn)算,先計(jì)算10*10=100,c=100(15)?(10):(15),結(jié)果c=15,例8.23 # define N 2 # define

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝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ù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論