C語言(譚浩強(qiáng))第4章模塊化程序設(shè)計(jì)_第1頁
C語言(譚浩強(qiáng))第4章模塊化程序設(shè)計(jì)_第2頁
C語言(譚浩強(qiáng))第4章模塊化程序設(shè)計(jì)_第3頁
C語言(譚浩強(qiáng))第4章模塊化程序設(shè)計(jì)_第4頁
C語言(譚浩強(qiáng))第4章模塊化程序設(shè)計(jì)_第5頁
已閱讀5頁,還剩55頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、編輯課件編輯課件 C語言是一種較現(xiàn)代的程序開發(fā)語言。它提供如下一些支持模塊化軟件開發(fā)的功能: (1) C語言用函數(shù)組織程序,在C語言程序中,一個程序由一個或多個程序文件組或,每一個程序文件就是一個程序模塊,每一個程序模塊由一個或多個函數(shù)組成。程序設(shè)計(jì)的任務(wù)就是設(shè)計(jì)一個個函數(shù),并且確定它們之間的調(diào)用關(guān)系。在設(shè)計(jì)函數(shù)時要使每個函數(shù)都具有各自獨(dú)立的功能和明顯的界面。 (2) 通過給變量定義不同的存儲類別,控制模塊內(nèi)部及外部的信息交換。 (3) 具有編譯預(yù)處理功能,為程序的調(diào)試、移植提供了方便,也支持了模塊化程序設(shè)計(jì)。編輯課件4.1.1 設(shè)計(jì)設(shè)計(jì)C語言程序就是設(shè)計(jì)函數(shù)語言程序就是設(shè)計(jì)函數(shù) 無論涉及的問

2、題是復(fù)雜還是簡單,規(guī)模是大還是小,用C語言設(shè)計(jì)程序,任務(wù)只有一種,就是編寫函數(shù),至少也要編寫一個main函數(shù)。執(zhí)行C程序也就是執(zhí)行相應(yīng)的main函數(shù)。即從main函數(shù)的第一個前花括號開始,依次執(zhí)行后面的語句,直到最后的后花括號為止。 模塊化程序設(shè)計(jì)有一個原則:就是每個模塊的規(guī)模一般不能太大(有人認(rèn)為要控制在4060行之間),以便于閱讀,便于檢查其中的錯誤。在C語言中,減少主函數(shù)規(guī)模的一項(xiàng)基本措施就是通過調(diào)用其它函數(shù)來實(shí)現(xiàn)主函數(shù)需要的一些功能。編輯課件main(void) f1();f2();return 0;操作系統(tǒng)f1() f11();f1() f21();f 2 2( ) ;f11()f2

3、1()f22()main()f1()f2()f22()f21()f11()參數(shù)參數(shù)參數(shù)參數(shù)參數(shù)返回返回返回返回返回編輯課件 為了定義函數(shù),必須首先了解函數(shù)的結(jié)構(gòu)。一個C語言函數(shù)的結(jié)構(gòu)形式如下:函數(shù)頭函數(shù)體編輯課件1. 函數(shù)頭函數(shù)類型 函數(shù)名(形式參數(shù)表列)一個函數(shù)的函數(shù)頭的結(jié)構(gòu)如下:(1)函數(shù)類型。指定函數(shù)值的類型,即函數(shù)返回值的類型。(2)函數(shù)名。函數(shù)名必須采用合法的用戶標(biāo)識符。(3)圓括號:在函數(shù)名后面的一對圓括號是“函數(shù)運(yùn)算符”,表示進(jìn)行函數(shù)運(yùn)算,函數(shù)運(yùn)算符具有很高的運(yùn)算優(yōu)先級別(4)形式參數(shù)表。形式參數(shù)表由寫在一對圓括號(函數(shù)運(yùn)算符)中的一系列參數(shù)組成。每一個參數(shù)由一個類型符和一個參數(shù)

4、名組成。參數(shù)名也應(yīng)當(dāng)是合法的用戶關(guān)鍵字。函數(shù)可以沒有參數(shù),這時在函數(shù)運(yùn)算符內(nèi)寫一個“void”,也可以空允白。編輯課件2. 函數(shù)體 函數(shù)體由一些語句組成。主要是三種類型的語句: 聲明語句:聲明在函數(shù)中要使用的變量等程序?qū)嶓w。 用來實(shí)現(xiàn)函數(shù)的功能的可執(zhí)行語句:包括若干流程控制 語句和表達(dá)式語句,。 return語句。使流程返回到調(diào)用處。這里主要介紹return語句的用法。當(dāng)函數(shù)執(zhí)行到return語句時,將停止本函數(shù)的執(zhí)行,將流程送回到調(diào)用處。同時,編譯器將函數(shù)分為三類進(jìn)行處理: 純粹計(jì)算型函數(shù),如squt()和sin()。這類函數(shù)將返回一個計(jì)算結(jié)果。 完成一項(xiàng)具體工作,返回完成的成敗。如prin

5、tf()執(zhí)行成功時,返回顯示的字節(jié)數(shù);失敗時,返回一個負(fù)整數(shù)。 只執(zhí)行一個過程的函數(shù),不產(chǎn)生返回值,其類型應(yīng)定義為void。C99規(guī)定,對于非void類型的函數(shù),必須使用有返回值的return語句。編輯課件int absolutevalue (int x)return (x=0?x:-x); void spc (int n)int i;for (i=0; in;i+)它printf ( );return;編輯課件 作用域指的是一個程序段中的代碼的作用范圍,在一個函數(shù)中定義的變量只在本函數(shù)中有效,在其它函數(shù)中不能使用這個變量,因此說,該變量的作用域是它所在的函數(shù)(從定義該變量的行開始到函數(shù)末尾)

6、。即使在不同的函數(shù)中定義了同名的變量,它們數(shù)也指的是不同的變量。編輯課件#include int func(int x) x=5;return x+3;int main(void)printf(x=%dn,x);return 0;這個程序企圖在main函數(shù)中使用func函數(shù)中的變量x。編譯這個程序,系統(tǒng)將給出如下編譯錯誤: c(13) : error C2065: x : undeclared identifier編輯課件空函數(shù)是一個不產(chǎn)生任何有效操作的函數(shù),但它卻是一個合法的C函數(shù)。例如函數(shù)void null (void)就是一個空函數(shù)??蘸瘮?shù)多使用在模塊化程序的設(shè)計(jì)或測試中。一般首先寫好m

7、ain函數(shù),確定需要調(diào)用的函數(shù),然后逐步編寫這些函數(shù),如果在有一些函數(shù)還未編寫好時想對已有倆編好的函數(shù)進(jìn)行調(diào)試,可以先用空函數(shù)(函數(shù)名用將來使用的實(shí)際函數(shù)名,如sort)放在程序中原定的位置上,這樣就可以調(diào)試程序的其它部分,等以后再逐步補(bǔ)上。編輯課件1. 函數(shù)定義函數(shù)定義是按照C語言的語法規(guī)則引入新的函數(shù),并提供如下信息: 函數(shù)的返回值類型(如果有); 參數(shù)的個數(shù)及類型和名稱; 調(diào)用函數(shù)時要執(zhí)行的代碼; 函數(shù)的有效性。編輯課件 函數(shù)聲明是對所用到的函數(shù)的特征進(jìn)行必要的聲明。編譯系統(tǒng)以函數(shù)聲明中給出的信息為依據(jù),對調(diào)用表達(dá)式進(jìn)行檢測,例如,形參與實(shí)參類型是否一致,使用函數(shù)返回值的類型是否正確,以

8、保證調(diào)用表達(dá)式與函數(shù)之間的參數(shù)正確傳遞。 聲明語句提供的必要信息包括:函數(shù)名,函數(shù)的類型,函數(shù)參數(shù)的個數(shù)、排列次序以及每個參數(shù)的類型。函數(shù)聲明的一般格式為:類型標(biāo)識符 函數(shù)名(類型標(biāo)識符形參,類型標(biāo)識符形參,);編輯課件設(shè)有一函數(shù)的定義為:double func (double a, int b, char c)/* 函數(shù)體*/與之相應(yīng)的函數(shù)聲明應(yīng)為:double func (double x, int y, char z);/* 注意末尾的分號 */編輯課件 一個函數(shù)中的函數(shù)體,只有在該函數(shù)被調(diào)用時才會執(zhí)行。在函數(shù)被調(diào)用時,將要進(jìn)行如下兩個操作: 將函數(shù)調(diào)用中的實(shí)際參數(shù)值傳送給函數(shù)定義中的形

9、式參數(shù); 將流程從調(diào)用處轉(zhuǎn)到被調(diào)用的函數(shù)的開頭,開始執(zhí)行函數(shù)體中的代碼。編輯課件 參數(shù)是函數(shù)調(diào)用時進(jìn)行信息交換的載體。實(shí)參是調(diào)用函數(shù)中的變量,形參是被調(diào)函數(shù)中的變量。在函數(shù)調(diào)用過程中實(shí)現(xiàn)實(shí)參與形參的結(jié)合。這稱為“虛實(shí)結(jié)合”。float add( );int main(void)float x=1.5, y=-5.7;printf (%f+%f=%fn, x,y, add(x,y);float add (unsigned int a, unsigned int b) printf(a=%u, b=%un, a,b);return (a+b); 編輯課件 程序進(jìn)行編譯時,并不為形式參數(shù)分配存儲空間

10、。只有在被調(diào)用時,形式參數(shù)才臨時地占有存儲空間,其過程如下:(1)調(diào)用開始,系統(tǒng)為形參開辟一個臨時存儲區(qū),形參與實(shí)參各占一個獨(dú)立的存儲空間。(2)然后將各實(shí)參之值傳遞給形參,這時形參就得到了實(shí)參的值。這種虛實(shí)結(jié)合方式稱為“值結(jié)合”。(3)函數(shù)返回時,臨時存儲區(qū)也被撤銷。 要特別注意在C程序中實(shí)參與形參結(jié)合的傳值傳值調(diào)用調(diào)用(call by value) 的特點(diǎn)。即函數(shù)中對形參變量的操作不會影響到調(diào)用函數(shù)中的實(shí)參變量,即形參值不能傳回給實(shí)參。編輯課件#include void swap (int x, int y);int main(void)int a=3, b=5;swap (a,b);pr

11、intf (a=%d, b=%dn, a,b);return 0;void swap (int x, int y)int temp;temp=x, x=y, y=temp; /* 交換變量的值交換變量的值 */printf(x=%d,y=%dn,x,y);執(zhí)行結(jié)果:執(zhí)行結(jié)果:x=5,y=3a=3,b=5編輯課件 由前面的學(xué)習(xí)已經(jīng)知道,一個函數(shù)可以調(diào)用另一個函數(shù)。C語言還允許一個函數(shù)自己調(diào)用自己(直接地或間接地調(diào)用自己)。于是形成一種特殊的函數(shù)結(jié)構(gòu)遞歸函數(shù),并且,前者稱為直接遞歸函數(shù)調(diào)用,后者稱為間接遞歸調(diào)用函數(shù)。編輯課件 遞歸計(jì)算n!的函數(shù)rfact( )。通常,n的階乘可以描述為: n!=1

12、2n但是,也可以描述為: n!= n(n-1)21或者可以寫為: n!= n(n-1)!更一般的形式是: 1 (x1)n n!= = n(n-1)?。?! (x1)編輯課件這就形成一個遞歸表達(dá)式。這個遞歸表達(dá)式可以用下面的函數(shù)實(shí)現(xiàn)。long rfact(int n)if (n0)printf(Negative argument to fact !n);exit (-1);else if (n=1)return (1);elsereturn (n*rfact (n-1); /*自己調(diào)用自己*/編輯課件rfact(5)5*rfact(4)4*rfact(3)3*rfact(2)2*rfact(1)1

13、2*13*25*244*6120編輯課件 據(jù)傳古代印度布拉瑪廟里僧侶們玩一種稱為漢諾塔的游戲,據(jù)說游戲結(jié)束就標(biāo)志著世界末日的到來。游戲的裝置是一塊銅板,上面有三根桿,最左桿自下而上、由大到小順序串有64個金盤,呈一個塔形(圖4.8)。游戲要求把左邊桿上的金盤全部移到最右邊的桿上,條件是一次只能夠動一個盤,并且不允許大盤在小盤上面。容易推出,n個盤從一根桿移到另一根桿需要2n-1次,所以64個盤的移動次數(shù)為:264-1=18,446,744,073,709,511,615,這是一個天文數(shù)字,即使一臺功能很強(qiáng)的現(xiàn)代計(jì)算機(jī)來解漢諾塔問題,每一微秒可能計(jì)算(不印出)一次移動,那么也需要幾乎100萬年。

14、而如果每秒移動一次,則需近5800億年。編輯課件下面設(shè)計(jì)一個模擬僧侶們移動盤子的算法。假定僧侶們要把n個盤子按題中的規(guī)定由a桿借助c桿移到b桿。模擬這一過程的算法稱為hanoi(n,a,b,c)。那么,很自然的想法是:a b cno1no2no3no4no1no3no4no2編輯課件第一步:先把上面的n-1個盤子設(shè)法借助b桿放到c桿,如圖4.8中的箭頭所示,記做hanoi(n-1, a,c,b)。第二步:把第n個盤子從a桿直接移到b桿,如圖4.8中的箭頭所示。第三步:把c桿上的n-1個盤子借助a桿移到b桿,如圖4.8中的箭頭所示,記做hanoi(n-1,c,b,a)。a b cno1no2no

15、3no4no1no3no4no2編輯課件#include void hanoi(int n, char a, char b ,char c);int main(void)int n;printf (*n);printf (*Program for simulating the solution*n);printf (* of the game of tower of Hanoi *n);printf (*n);printf (Please enter the number of disks to be moved:);scanf (%d, &n);編輯課件hanoi (n,a,b,c)

16、;return 0;void hanoi (int n, char a, char b, char c)/*漢諾塔問題*/if (n0)hanoi (n-1, a,c,b);printf ( Move disc %d from pile %c to %cn, n,a,b); (n-1, c,b,a);編輯課件編輯課件h(3,a,b,c)h(2,a,c,b); no3:a-b; h(2,c,b,a);h(2,a,b,c)h(1,a,b,c); no2:a-c; h(1,b,c,a);h(1,a,b,c)h(0,a,c,b); no0:a-b; h(0,c,b,a);h(1,b,c,a)h(0,b

17、,a,c);no1:b-c; h(0,a,c,b);h(1,c,a,b)h(0,c,b,a); no1:c-a; h(0,b,a,c);h(1,a,b,c)h(0,a,c,b); no1:a-b; h(0,c,b,a);h(2,c,b,a)h(1,c,a,b); no2:c-b; h(1,a,b,c);編輯課件 變量是對程序中數(shù)據(jù)存儲的抽象。如前所述,C語言程序中的變量都是有類型的,數(shù)據(jù)類型是變量的運(yùn)算屬性的抽象,決定了該變量的取值范圍和可以施加的運(yùn)算種類。除此之外,變量還有變量一些屬性,例如: 一個變量在程序的哪個范圍內(nèi)是可以使用的變量的可用域; 它什么時候生成以及什么時候被撤消變量的生存期

18、; 它存儲在什么哪種類型的存儲器中以及用什么機(jī)制進(jìn)行存儲變量的存儲區(qū)。這些都稱為變量的存儲屬性。編輯課件1. 局部變量和全局變量變量的可用域是指一個變量的標(biāo)識符在程序的哪個域內(nèi)才是可以被識別的,也稱為可見(可見(或可用)的。大體上可以分為兩種:全局可用全局變量全局變量與局部可用局局部變量部變量。局部變量是定義在一個程序塊(用一對花括號括起的語句塊)內(nèi)的變量。程序塊可能是一個函數(shù)體(主函數(shù)),也可能是一個循環(huán)體或是選擇結(jié)構(gòu)中的一個分支語句塊,也可以是任何一個用花括號擴(kuò)起的語句塊。而全局變量是定義在函數(shù)之外的變量。一般說來,定義在什么范圍的變量,其作用域就在那個范圍,并且在從定義語句開始到這個域結(jié)

19、束的范圍(域)內(nèi)被使用,在這個域之外是不可見的。在C語言中,凡是聲明在函數(shù)內(nèi)部的變量都是局部變量。編輯課件#include int main(void)/* printf(a1=%d,a); */b的作用域a的作用域 int a=3; printf(a2=%d,a); int b=5; printf(b1=%d,b); /* printf(b2=%d,b); */printf(a3=%d,a);return 0;則運(yùn)行可以得到如下結(jié)果:a2=3b1=5a3=3編輯課件任何一個運(yùn)行中的程序,在內(nèi)存中都被分成代碼區(qū)和數(shù)據(jù)區(qū)兩大部分,而數(shù)據(jù)區(qū)又被分為靜態(tài)存儲區(qū)、自動存儲區(qū)和動態(tài)分配區(qū)等三部分。自動存

20、儲區(qū)是按棧組織的存儲區(qū)。除特別聲明的外,局部變量通常被存放在棧區(qū)。這些變量在進(jìn)入所在的塊時被創(chuàng)建,所在的塊結(jié)束時被撤銷,當(dāng)所在的塊結(jié)束后,各變量的值不再保留。并且,變量必須有程序員顯式地進(jìn)行初始化,否則它們的初始值是不確定的。前面例存儲區(qū)是在程序編譯時就分配的存儲區(qū),分配在靜態(tài)存儲區(qū)的變量在程序開始執(zhí)行時被創(chuàng)建并自動初始化(數(shù)值變量被初始化為0),當(dāng)程序結(jié)束時才被撤銷。所以常稱靜態(tài)變量的生存期是永久的。全局變量就是被分配在靜態(tài)存儲區(qū)的。下面的例子說明將例4.8中的程序改用全局變量實(shí)現(xiàn)后的情形。編輯課件根據(jù)程序中實(shí)際應(yīng)用的需要,C語言將可用域和生存期整合成4種存儲類型: 局部自動類型,在函數(shù)內(nèi)部

21、用標(biāo)識符auto或register聲明。 靜態(tài)局部類型,在函數(shù)內(nèi)部,使用static聲明。 靜態(tài)全局類型,在函數(shù)外部,使用static聲明,也稱靜態(tài)外部變量。 全局類型,不需要標(biāo)識符聲明。在函數(shù)外部直接聲明即可,通稱外部變量。編輯課件編輯課件 可以被多處修改將引起的副作用,又可以使函數(shù)基于前一次調(diào)用的值的基礎(chǔ)上工作。編輯課件#include void increment(void);int main(void)increment ( );increment ( );increment ( );return 0;void increment(void)int x=0; /*auto*/x+;pr

22、intf (%dn,x);運(yùn)行結(jié)果:運(yùn)行結(jié)果:111編輯課件#include void increment (void);int main(void)increment ( );increment ( );increment ( );return 0;void increment (void)static int x=0; /*使用了使用了static說明符說明符 */x+;printf (%dn,x);運(yùn)行結(jié)果:運(yùn)行結(jié)果:1?23編輯課件 在多文件程序中,用static聲明外部變量,這樣,該外部變量的作用域僅限于所在的文件,而不用static聲明的外部變量的作用域?yàn)檎麄€程序。例如,某個程序中

23、要用到大量函數(shù),而有幾個函數(shù)需要共同使用幾個全局變量時,可以將這幾個函數(shù)組織在一個文件中,而將這幾個全局變量定義為靜態(tài)的,以保證它們不會與其他文件中的變量發(fā)生名字沖突,保證文件的獨(dú)立性。編輯課件嚴(yán)格地說,定義與聲明是兩個不相同的概念。聲明的含義更廣一些,定義的含義稍窄一些,定義是聲明的一種形式,定義具有分配存儲的功能,凡是定義都屬于聲明,稱為定義性聲明(定義性聲明(defining declaration)。另一種聲明稱為引用性聲明引用性聲明(referencing declaration),它僅僅是對編譯系統(tǒng)提供一些信息,聲明并不都是定義。前幾章例題程序中定義變量的聲明語句,是定義性聲明,為

24、方便,一般簡稱為定義。定義。而函數(shù)聲明就是引用性聲明,它和函數(shù)定義的作用是不同的。一般把引用性聲明簡稱為聲明聲明(狹義的聲明明)。對同一作用域中的同一變量只能定義一次,如果對同一變量定義多次,就會出現(xiàn)語法錯誤。在定義變量時可以用auto,static, register等關(guān)鍵字聲明該變量的存儲類型。編輯課件對于外部變量(除了靜態(tài)全局變量外),除了可以定義一次外部變量外,還可以多次進(jìn)行聲明(引用性聲明)。(1)通過聲明將外部變量的作用域在本文件范圍內(nèi)擴(kuò)充向前引用編輯課件通常,一個外部變量的作用域是從其定義點(diǎn)到本文件末尾。對于位于定義點(diǎn)之前的函數(shù),可以用extern聲明使變量的作用域擴(kuò)充到需要用到

25、它的函數(shù)。(2)利用聲明語句將作用域擴(kuò)大到其他文件建立對象的外部鏈接假設(shè)一個程序由兩個以上的文件組成。當(dāng)一個全局變量定義在文件file1中時,在另外的文件中使用extern聲明,可以通知編譯系統(tǒng)一個信息:“此變量到外部去找”?;蛘哒f在鏈接時,告訴鏈接器:“到別的文件中找這個變量的定義”。編輯課件 (4) 全局變量的副作用 前面已提到,如果沒有外部變量,函數(shù)只能通過參數(shù)與外界發(fā)生數(shù)據(jù)聯(lián)系,有了外部變量以后,增加了一條與外界傳遞數(shù)據(jù)的渠道。這種方法有利有弊。外部變量作為公共信息的一種載體,雖然給程序設(shè)計(jì)帶來一些方便,但也會產(chǎn)生一些副作用 編輯課件 C語言除了可以為程序開辟棧區(qū)、堆區(qū)、靜態(tài)區(qū)外,還可

26、以開辟一個只讀區(qū)。既然只讀區(qū)是內(nèi)存的一個區(qū),所以數(shù)據(jù)是以變量的形式存儲的,但它又是只讀的,即不可修改的。所以這也就是把變量定義為只讀變量。定義只讀變量的方法是在聲明變量時使用修飾符const。格式為:const 數(shù)據(jù)類型 變量1=初始表達(dá)式1,變量2=初始表達(dá)式2,編輯課件4.3.1 分別編譯分別編譯 C語言是一種支持模塊化程序設(shè)計(jì)的語言,它允許將一個大型程序分成多個程序文件分別進(jìn)行編譯。這樣的好處在于 當(dāng)程序的一個局部有錯誤或?qū)植窟M(jìn)行了修改時,可以只重新編譯該局部,不需要將整個程序都重新編譯。 某些經(jīng)過考驗(yàn)的函數(shù)的目標(biāo)代碼可以添加為的庫函數(shù),供其他程序中使用。編輯課件 多文件程序的編譯、鏈

27、接過程是比較麻煩的。為了方便用戶進(jìn)行多文件程序的編譯、鏈接,各種程序開發(fā)軟件都提供了用項(xiàng)目(project)管理多文件程序的編譯和鏈接過程。其使用方法因開發(fā)工具而異,請參考有關(guān)手冊。編輯課件用戶顯式地保證程序一致性的基本方法是保持聲明的一致性。保持聲明一致性的簡單辦法是提供一個頭文件,讓頭文件中的信息作為各模塊之間的接口信息,有利于提供可重用的模塊。使用頭文件將把程序分為程序頭和程序體兩部分。好的頭文件應(yīng)包含如下一些內(nèi)容: 類型定義,如定義一個枚舉類型enum color RED,BLUE,GREEN,YELLOW; 函數(shù)聲明,如extern int strlen const char*; 嵌

28、入函數(shù)聲明,如inline char get() return *p+; 數(shù)據(jù)聲明,如extern int a; 常量定義,如const float pi=3.141593; 包含指令,如#include 編輯課件 宏定義,如#define case break; case 注釋好的頭文件不能包含以下內(nèi)容: 一般函數(shù)定義 數(shù)據(jù)定義,如int a; 常量聚集定義,如 const tbl=/* */;用戶頭文件是由用戶自己定義的頭文件。系統(tǒng)將用雙引號方式進(jìn)行搜索。 程序員可以用它們建立各文件之間的信息窗口。應(yīng)當(dāng)注意,修改了頭文件時,所有涉及該頭文件的程序都應(yīng)重新編譯, 所以在編制頭文件時應(yīng)盡量考慮

29、周全;另外,當(dāng)使用很多頭文件時,常常有重復(fù)嵌入的情形發(fā)生, 在這種情形下,應(yīng)防止標(biāo)識符重復(fù)定義的錯誤。為避免這些錯誤, 應(yīng)使用條件編譯來測試有無重復(fù)定義。編輯課件 編譯預(yù)處理是以“#”開頭的一些命令,它通知編譯系統(tǒng):在進(jìn)行正式編譯前應(yīng)當(dāng)先進(jìn)行一些前期工作(即編譯預(yù)處理)。目前,C語言的編譯預(yù)處理功能主要有如下一些:(1)文件包含,使用命令:#include。(2)宏定義,使用命令:#define、#undef。(3)條件編譯,使用命令:#if、#ifdef、#ifndef、#else、#endif、#elif、defind。(4)提供行號信息,使用命令:#line。(5)編譯雜注,使用命令:#

30、progma。(6)錯誤信息,使用命令:#error。 在這些編譯預(yù)處理中,應(yīng)用最多的就是對宏的處理。它允許程序員使用define定義并應(yīng)用宏名字書寫C語言程序,同時也指示編譯器在正式編譯前通過宏替換,使程序能按照C語言的語法進(jìn)行編譯。編輯課件 define命令最簡單的應(yīng)用是將一個字符串定義為一個宏名,格式為: define 宏名宏名 字符串字符串 編譯預(yù)處理時,預(yù)處理程序?qū)殉绦蛭募性谠摵甓x之后的所有宏名,用#define命令中定義的字符串(稱為宏體)替換,這個過程稱為宏替換。符號常數(shù)的定義就是這種宏定義的一種應(yīng)用。例如#define PI 3.14159265#define RADIU

31、S 2.0使用宏定義的好處是:(1) 提高了程序的可讀性。如果人們看到以下語句return (2.0* 3.1415926536* 2.0);編輯課件和return (3.1415926536* 2.0* 2.0);是否能很快地看出它們在計(jì)算什么呢?顯然不能。如果寫成下面的形式return (2.0* PI* RADIUS);和return (PI *RADIUS* RADIUS);任何人一眼都可以看出:這是在計(jì)算圓周長和圓面積。使用宏定義可以提高可理解性。(2) 易修改性好。如要將RADIUS的值由2.0修改為3.0,只要在define命令中修改一處便可。而在不使用宏定義的文件中,要將3處的

32、2.0修改為3.0,而且很可能也錯把circum函數(shù)中的第一個返回語句也修改成return (3.0*3.1415926536*3.0);編輯課件(3)宏定義可以給程序設(shè)計(jì)帶來許多方便。如熟悉PASCAL的讀者,完全可以用自己已習(xí)慣的風(fēng)格來寫程序。#define BEGIN #define END #define AND &#define OR |#define NOT !void func(void)BEGINif(a AND b)6) else if(c OR d)3) else if(NOT(e=9)END如果沒有前面的宏定義,后面的程序是不符合C語言語法的。只有經(jīng)過編譯預(yù)處理,

33、程序部分符合C語言的語法。編輯課件(1)在#define命令中,宏名字與字符串(宏體)之間用一個或多個空格分隔。(2)宏名編輯課件#define A NAME SMISS則實(shí)際進(jìn)行的宏定義是A為宏名字,宏體是“NAME SMISS”。 C程序員一般都習(xí)慣用大寫字母定義宏名字。這樣的表示方法使宏名與變量名有明顯的區(qū)別,以避免混淆。此外有助于快速識別要發(fā)生宏替換的位置,提高程序的可讀性。 不能進(jìn)行宏名字的重定義。(3)定義一個宏名字以后,就可以在后面使用這個宏名字了,包括在后面的宏定義中使用。例如求圓的周長和面積的程序可以改寫為#include 編輯課件#define PI3.1415926#de

34、fine R1.0#define CIRCUM2.0*PI*R /* 使用了前面定義的R和PI */#define AREAPI*R*R int main(void) printf(“The circum is %f and area is %fn”,CIRCUM,AREA); 這種宏定義稱為嵌套宏定義。運(yùn)行這個程序的結(jié)果為:The circum is 6.283185 and area is 3.141593下面是另外一種形式的宏定義:#include #define PI 3.14159265#define RADIUS 1.0#define CIRCUM return(2.0*PI* R

35、ADIUS); /* 最后的分號是return語句的一部分 */編輯課件#define AREA return(PI* RADIUS* RADIUS);double circum( )CIRCUMdouble area( )AREAint main(void) printf(The circum is %f and area is %fn,circum(),area();(4)不能進(jìn)行的宏替換: 不可以替換作為用戶標(biāo)識符中的成分。例如,在例4.23中,不可以用“R”替換“CIRCUM”中的“R”。 不能替換字符串常量中的成分。編輯課件#include #define PI3.1415926#define R1.0#define CIRCUM2.0*PI*R#define AREAPI*R*R int main(void) printf(“The CI

溫馨提示

  • 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論