版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第5章函數(shù)和編譯預(yù)處理5.3函數(shù)的參數(shù)傳遞5.4函數(shù)的嵌套調(diào)用5.5函數(shù)的遞歸調(diào)用5.6變量的作用域和存儲5.7編譯預(yù)處理目錄5.1模塊化的設(shè)計思想5.2函數(shù)的定義、調(diào)用和函數(shù)聲明5.1模塊化的設(shè)計思想程序員在設(shè)計一個復(fù)雜的應(yīng)用程序時,往往也是把整個程序劃分為若干功能較為單一的程序模塊,然后分別予以實(shí)現(xiàn),最后再把所有的程序模塊像搭積木一樣裝配起來,這種在程序設(shè)計中分而治之的策略,被稱為模塊化程序設(shè)計方法。5.1模塊化的設(shè)計思想如何設(shè)計和調(diào)用函數(shù)呢?將【案例3-7】用while循環(huán)語句實(shí)現(xiàn)1~100自然數(shù)之和的程序進(jìn)行改寫,用函數(shù)實(shí)現(xiàn)求1~100自然數(shù)之和。下面左側(cè)為用子函數(shù)實(shí)現(xiàn)的源程序,右側(cè)為【案例3-7】源程序。5.1模塊化的設(shè)計思想C語言函數(shù)有兩種,一種是由系統(tǒng)提供的標(biāo)準(zhǔn)函數(shù),這種函數(shù)用戶可以直接使用,叫做庫函數(shù);另一種是用戶自定義的函數(shù),這種函數(shù)用戶必須先定義后使用。TurboC系統(tǒng)提供了400多個標(biāo)準(zhǔn)庫函數(shù),按功能可以分為:類型轉(zhuǎn)換函數(shù)、字符判別與轉(zhuǎn)換函數(shù)、字符串處理函數(shù)、標(biāo)準(zhǔn)I/O函數(shù)、文件管理函數(shù)和數(shù)學(xué)運(yùn)算函數(shù)等。它們執(zhí)行效率高,用戶需要時,可在程序中直接進(jìn)行調(diào)用。從函數(shù)的形式上看,一個C語言程序必須包含一個且只有一個main函數(shù),由main函數(shù)開始調(diào)用其他函數(shù),其他函數(shù)也可相互調(diào)用,但最終返回主函數(shù)結(jié)束程序。其他函數(shù)一般就是由用戶自定義的函數(shù)。5.2函數(shù)的定義、調(diào)用和函數(shù)聲明1.函數(shù)的定義格式說明:(1)函數(shù)類型指定所定義函數(shù)返回值的類型,可以是簡單類型、void類型或構(gòu)造類型等,默認(rèn)為int型。當(dāng)函數(shù)類型為void時,表示函數(shù)無返回值。當(dāng)函數(shù)類型為int時,可省略其類型的說明。(2)函數(shù)名是函數(shù)的標(biāo)識符,遵循C語言標(biāo)識符的命名規(guī)則,區(qū)分大小寫。后面一對圓括號()里為函數(shù)的參數(shù)列表。函數(shù)定義的第一行又可被稱為“函數(shù)頭”。(3)函數(shù)體是一個復(fù)合語句,即用花括號{}括起來的語句序列。5.2.1函數(shù)的定義5.2函數(shù)的定義、調(diào)用和函數(shù)聲明(4)對于有返回值的函數(shù),必須用帶表達(dá)式的return語句來結(jié)束函數(shù)的運(yùn)行,返回值的類型應(yīng)與函數(shù)類型相同。如果return語句中表達(dá)式值與函數(shù)定義的類型不一致,則以函數(shù)定義類型為準(zhǔn),并自動將return語句中的表達(dá)式的值轉(zhuǎn)換為函數(shù)返回值的類型。例如:return;/*當(dāng)函數(shù)類型為void類型時無返回值,直接返回*/return0;/*返回一個常量*/returna>b?a:b;/*返回一個不帶括號的表達(dá)式*/return(a+b);/*返回一個帶括號的表達(dá)式*/(5)形式參數(shù)簡稱形參,處在函數(shù)定義部分的函數(shù)名后的圓括號中。形式參數(shù)表可以為空,表示沒有參數(shù)(無參函數(shù)),也可以由多個參數(shù)組成。當(dāng)形式參數(shù)表中有多個參數(shù)時,參數(shù)與參數(shù)之間用逗號隔開。5.2.1函數(shù)的定義5.2函數(shù)的定義、調(diào)用和函數(shù)聲明2.形式參數(shù)列表說明形式參數(shù)列表有以下兩種形式:(1)void或空無參函數(shù)一般不需要返回函數(shù)值,因此可以不寫類型標(biāo)志符(或?qū)懗煽疹愋蛌oid)。例如:intsum(void)/*定義一個沒有參數(shù)的函數(shù)sum*/{inti,s=0;for(i=1;i<=10;i++)s+=i;returns;}函數(shù)的功能是計算并返回從1到10的整數(shù)和。5.2.1函數(shù)的定義5.2函數(shù)的定義、調(diào)用和函數(shù)聲明(2)參數(shù)類型名1參數(shù)1,參數(shù)類型名2參數(shù)2,……,參數(shù)類型名n參數(shù)n函數(shù)包含一個或多個參數(shù),每個參數(shù)必須標(biāo)注具體的數(shù)據(jù)類型,這樣的函數(shù)又稱為有參函數(shù)。例如:intmax(inta,intb)/*定義一個有2個參數(shù)a、b的函數(shù)max*/{ intm=0; if(a>b)m=a; elsem=b; returnm;}5.2.1函數(shù)的定義5.2函數(shù)的定義、調(diào)用和函數(shù)聲明函數(shù)的功能是求兩個整數(shù)的較大值。如果按照傳統(tǒng)的函數(shù)寫法,可以將參數(shù)列表中的變量定義放在函數(shù)頭和函數(shù)左花括號之間。例如上例可改寫為:intmax(a,b)/*定義一個有2個參數(shù)的函數(shù)max*/inta,b;/*將形式參數(shù)a、b的類型說明放在函數(shù)頭和函數(shù)體之間*/{intm=0;if(a>b)m=a;elsem=b;returnm;}這種寫法適合于參數(shù)有多個的情況。提示:函數(shù)頭部分需要注意無論函數(shù)是否有形式參數(shù),函數(shù)名后的圓括號不可省略,并且圓括號之后不能接“;”。5.2.1函數(shù)的定義5.2函數(shù)的定義、調(diào)用和函數(shù)聲明函數(shù)的使用是通過函數(shù)調(diào)用語句來完成的。C語言是通過main函數(shù)來調(diào)用其他函數(shù),其他函數(shù)之間可相互調(diào)用,但不能調(diào)用main函數(shù)。函數(shù)被調(diào)用時獲得程序控制權(quán),調(diào)用完成后,返回到調(diào)用語句的后面語句。函數(shù)調(diào)用語句一般格式如下:說明:(1)函數(shù)調(diào)用可以出現(xiàn)在表達(dá)式中,也可以做為一條單獨(dú)的語句出現(xiàn)。如:s=sum();/*計算1+2+……+10的值*/z=max(5,8);/*計算5、8中的較大值*/z=max(5+4,8*2);/*計算(5+4)和(8*2),即9和16中的較大值*/z=max(x,y);/*計算x、y中較大值,x、y為實(shí)際參數(shù)*/函數(shù)名(實(shí)際參數(shù)列表)5.2.2函數(shù)的調(diào)用5.2函數(shù)的定義、調(diào)用和函數(shù)聲明(2)函數(shù)的參數(shù)分為實(shí)際參數(shù)和形式參數(shù)兩種,分別簡稱為實(shí)參和形式。其中實(shí)際參數(shù)是在調(diào)用的函數(shù)中的參數(shù),一般是具有實(shí)際的值的常量、變量或表達(dá)式,而形式參數(shù)是寫在函數(shù)頭中函數(shù)名后面括號中的變量。例如上面例子中函數(shù)頭:intmax(inta,intb)中的a、b就是形式參數(shù),而語句:z=max(x,y);中的x、y就是實(shí)際參數(shù)。(3)實(shí)參的個數(shù)必須與形參的個數(shù)一致。實(shí)際參數(shù)(簡稱實(shí)參)的個數(shù)多于一個時,各實(shí)參之間用逗號隔開。(4)在定義的函數(shù)中,必須指定形參的類型,并且實(shí)參的類型必須與形參的類型一一對應(yīng)。(5)實(shí)參可以和形參同名。5.2.2函數(shù)的調(diào)用5.2函數(shù)的定義、調(diào)用和函數(shù)聲明編譯程序在處理函數(shù)調(diào)用時,必須從程序中獲得完成函數(shù)調(diào)用所必需的接口信息。函數(shù)的聲明是對函數(shù)類型、名稱等的說明。為函數(shù)調(diào)用提供接口信息,對函數(shù)原型的聲明是一條程序說明語句。函數(shù)原型的聲明就是在函數(shù)定義的基礎(chǔ)上去掉函數(shù)體,后面加上分號“;”。其定義格式如下:5.2.3函數(shù)的聲明5.2函數(shù)的定義、調(diào)用和函數(shù)聲明例如:intmax(inta,intb); /*具有兩個整型形參,函數(shù)類型為整型的函數(shù)聲明*/和完整的函數(shù)定義不同,形參表可以只給出形參的類型,形參名可以省略。例如:intmax(int,int);/*與上面聲明功能相同,只不過省略了形參名*/之所以需要函數(shù)的聲明,是為了獲得調(diào)用函數(shù)的權(quán)限。例如:#include"math.h"其中math.h文件包含了很多數(shù)學(xué)函數(shù)的原型聲明。這樣做的好處是方便調(diào)用和保護(hù)源代碼。5.2.3函數(shù)的聲明5.2函數(shù)的定義、調(diào)用和函數(shù)聲明【案例5-1】用函數(shù)實(shí)現(xiàn)求兩個整數(shù)中較大的值。打開源程序程序運(yùn)行結(jié)果9/22/20235.3函數(shù)的參數(shù)傳遞函數(shù)調(diào)用需要向子函數(shù)傳遞數(shù)據(jù),一般是通過實(shí)參將數(shù)值傳遞給形參。實(shí)參向形參的參數(shù)傳遞有兩種形式:值傳遞和地址傳遞。(1)值傳遞:是指單向的數(shù)據(jù)傳遞(將實(shí)參的值賦給形參),傳遞完成后,對形參的任何操作都不會影響實(shí)參的值。(2)地址傳遞:將實(shí)參的地址傳遞給形參,使形參指向的數(shù)據(jù)和實(shí)參指向的數(shù)據(jù)相同(相當(dāng)于實(shí)參和形參在內(nèi)存中共用同一個空間),因而被調(diào)函數(shù)的操作會直接影響實(shí)參指向的數(shù)據(jù)。地址傳遞又稱為指針傳遞或傳址,在后面的指針章節(jié)中詳細(xì)介紹。5.3函數(shù)的參數(shù)傳遞【案例5-2】編寫一個子函數(shù)change,有兩個整型形參,在子函數(shù)中交換這兩個形參的值。編寫子函數(shù)add,有一個數(shù)組作為函數(shù)形參,在該函數(shù)中將數(shù)組中每個元素的值都乘2。通過該例程了解值傳遞和地址傳遞的區(qū)別。打開源程序程序運(yùn)行結(jié)果5.4函數(shù)的嵌套調(diào)用C語言程序執(zhí)行時都從main函數(shù)開始,在main函數(shù)中遇到子函數(shù)調(diào)用語句,則調(diào)用該子函數(shù),若有其他函數(shù)也可相互調(diào)用,但執(zhí)行完子函數(shù)后最終必須返回主函數(shù),直到程序結(jié)束。函數(shù)的嵌套調(diào)用是指在執(zhí)行被調(diào)用函數(shù)時,被調(diào)用函數(shù)又調(diào)用了其他函數(shù)。5.4函數(shù)的嵌套調(diào)用例如,在main函數(shù)中可以調(diào)用A函數(shù),在調(diào)用A函數(shù)的過程中可以調(diào)用B函數(shù);當(dāng)B函數(shù)調(diào)用結(jié)束后返回到A函數(shù),當(dāng)A函數(shù)調(diào)用結(jié)束后,再返回到main函數(shù),這就是函數(shù)的嵌套調(diào)用。其調(diào)用過程如圖5-1所示。圖5-1函數(shù)的嵌套調(diào)用過程示意圖5.4函數(shù)的嵌套調(diào)用函數(shù)嵌套調(diào)用時需要注意的以下兩點(diǎn)。(1)C語言程序中的函數(shù)定義都是平行、相互獨(dú)立的。也就是說在一個函數(shù)定義的內(nèi)部,不能定義其他函數(shù),即函數(shù)的定義不允許嵌套。(2)一個函數(shù)既可以被其他函數(shù)調(diào)用,也可以調(diào)用其他函數(shù),這就是函數(shù)的嵌套調(diào)用。下面通過一個案例來了解一下函數(shù)的嵌套調(diào)用。5.4函數(shù)的嵌套調(diào)用【案例5-3】編寫兩個子函數(shù),子函數(shù)fac是求一個整數(shù)n的階乘,子函數(shù)add是求兩個整數(shù)a和b的階乘的和。在主函數(shù)中輸入兩個正整數(shù),求這兩個數(shù)的階乘的和。打開源程序程序運(yùn)行結(jié)果5.5函數(shù)的遞歸調(diào)用函數(shù)通過其函數(shù)體中的語句直接或間接地調(diào)用自身,稱為遞歸調(diào)用,這樣的函數(shù)稱為遞歸函數(shù)。遞歸函數(shù)一般都有一個條件語句,執(zhí)行語句分兩部分,一個是結(jié)束遞歸的終值,一個是遞歸的返回表達(dá)式,表達(dá)式中有該函數(shù)的自身調(diào)用。5.5函數(shù)的遞歸調(diào)用遞歸函數(shù)是無終止的調(diào)用自身。要避免這種情況的發(fā)生,使用遞歸解決的問題應(yīng)滿足兩個基本條件:(1)問題的轉(zhuǎn)化。有些問題不能直接求解或難以求解,但它可以轉(zhuǎn)化為一個新問題,這個新問題相對比原問題簡單或更接近解決方法。這個新問題的解決與原問題一樣,可以轉(zhuǎn)化為下一個新問題,……。(2)轉(zhuǎn)化的終止條件。原問題到新問題的轉(zhuǎn)化是有條件的,次數(shù)是有限的,不能無限次數(shù)地轉(zhuǎn)化下去。這個終止條件也稱為邊界條件,相當(dāng)于遞推關(guān)系中的初始條件。5.5函數(shù)的遞歸調(diào)用【案例5-4】設(shè)計遞歸函數(shù)fact(n),計算并返回n的階乘值。打開源程序程序運(yùn)行結(jié)果9/22/20235.6變量的作用域和存儲類型在C語言中,由用戶名命名的標(biāo)識符都有一個有效的作用域。不同的作用域允許相同的變量和函數(shù)出現(xiàn),同一作用域變量和函數(shù)不能重復(fù)。依據(jù)變量作用域的不同,C語言變量可以分為局部變量和全局變量兩大類。在函數(shù)內(nèi)部或復(fù)合語句內(nèi)部定義的變量,稱為局部變量。函數(shù)的形參也屬于局部變量。在函數(shù)外部定義的變量,稱為全局變量。有時將局部變量稱為內(nèi)部變量,全局變量稱為外部變量。5.6.1變量的作用域5.6變量的作用域和存儲類型變量的作用域要注意以下幾點(diǎn):(1)主函數(shù)中定義的變量只能在主函數(shù)中使用,不能在其他函數(shù)中使用。因?yàn)橹骱瘮?shù)也是一個函數(shù),它與其他函數(shù)是平等關(guān)系。(2)不同的函數(shù)內(nèi)可以定義相同名字和內(nèi)部變量,它們互不影響。(3)形參變量屬于被調(diào)函數(shù)的內(nèi)部變量,實(shí)參變量屬于主調(diào)函數(shù)的內(nèi)部變量。(4)在函數(shù)體內(nèi)的復(fù)合語句中可以定義變量,其作用域只在復(fù)合語句范圍內(nèi),這種復(fù)合語句也稱為“分程序”或“程序段”。(5)在同一源程序文件中,如果全局變量與局部變量同名,則在局部變量的作用范圍內(nèi)全局變量不起作用。(6)全局變量的使用會降低函數(shù)的通用性、可靠性、清晰性,因此建議沒有必要時不要使用全局變量。5.6.1變量的作用域5.6變量的作用域和存儲類型變量的生存期是指變量值在程序運(yùn)行過程中的存在時間。C語言變量的生存期可以分為靜態(tài)生存期和動態(tài)生存期。一個程序占用的內(nèi)存空間通常分為兩個部分:程序區(qū)和數(shù)據(jù)區(qū),數(shù)據(jù)區(qū)也可以分為靜態(tài)存儲區(qū)和動態(tài)存儲區(qū)。其中程序區(qū)中存放的是可執(zhí)行程序的機(jī)器指令。靜態(tài)存儲區(qū)中存放的是靜態(tài)數(shù)據(jù),如靜態(tài)常量、靜態(tài)變量。動態(tài)存儲區(qū)中存放的是動態(tài)數(shù)據(jù),如動態(tài)變量。動態(tài)存儲區(qū)分為堆內(nèi)存區(qū)和棧內(nèi)存區(qū),堆和棧是不同的數(shù)據(jù)結(jié)構(gòu),棧由系統(tǒng)管理,堆由用戶管理。5.6.2變量的生存期5.6變量的作用域和存儲類型靜態(tài)變量是指main函數(shù)執(zhí)行前就已經(jīng)分配內(nèi)存的變量,其生存期為整個程序執(zhí)行期;動態(tài)變量是在程序執(zhí)行到該變量聲明的作用域才臨時分配內(nèi)存,其生存期僅在其作用域內(nèi)。生存期和作用域是不同的概念,分別從時間和空間上對變量的使用進(jìn)行界定,相互關(guān)聯(lián)又不完全一致。例如,靜態(tài)變量的生存期貫穿整個程序,但作用域是從聲明位置開始到文件結(jié)束。5.6.2變量的生存期5.6變量的作用域和存儲類型【案例5-5】變量作用域演示程序。打開源程序程序運(yùn)行結(jié)果5.6變量的作用域和存儲類型1.自動(auto)類型變量的存儲類型有4種,分別由4個關(guān)鍵字表示:auto(自動)、register(寄存器)、static(靜態(tài))和extern(外部)。例如,在前面章節(jié)各程序中所使用的變量,它們的存儲類型均為auto類型。例如:autointx;/*定義一個自動整型變量x,auto可省略*/registerfloaty;/*定義一個寄存器浮點(diǎn)型變量y*/staticdoublez;/*定義一個靜態(tài)雙精度浮點(diǎn)型變量z*/externlongs;/*聲明(不是定義)一個外部長整型變量s*/存儲類型類型名變量名表;5.6.3變量的存儲類型5.6變量的作用域和存儲類型2.寄存器(register)類型用register定義的變量是一種特殊的自動變量,稱為寄存器變量。這種變量建議編譯程序?qū)⒆兞恐械臄?shù)據(jù)存放在寄存器中,而不像一般的自動變量那樣,占用內(nèi)存單元,可以大大提高變量的存取速度。一般情況下,變量的值都是存儲在內(nèi)存中的。為提高執(zhí)行效率,C語言允許將局部變量的值存放到寄存器中,這種變量就稱為寄存器變量。5.6.3變量的存儲類型5.6變量的作用域和存儲類型3.靜態(tài)(static)類型全局變量和局部變量都可以用static來聲明,但意義不同。全局變量總是靜態(tài)存儲,默認(rèn)值為0。全局變量前加上static表示該變量只能在本程序文件內(nèi)使用,其他文件無使用權(quán)限。對于全局變量,static關(guān)鍵字主要用于在程序包含多個文件時限制變量的使用范圍,對于只有一個文件的程序有無static都是一樣的。局部變量定義在函數(shù)體(或復(fù)合語句)內(nèi)部,用static來聲明時,該變量為靜態(tài)局部變量。靜態(tài)局部變量屬于靜態(tài)存儲,在程序執(zhí)行過程中,即使所在函數(shù)調(diào)用結(jié)束也不釋放。靜態(tài)局部變量定義并不初始化,則自動賦以數(shù)字“0”(整型和實(shí)型)或'\0'(字符型)。每次調(diào)用定義靜態(tài)局部變量的函數(shù)時,不再重新為該變量賦初值,只是保留上次調(diào)用結(jié)束時的值,所以要注意多次調(diào)用函數(shù)時靜態(tài)局部變量每次的值。5.6.3變量的存儲類型5.6變量的作用域和存儲類型4.外部(extern)類型在默認(rèn)情況下,在文件域中用extern聲明(注意不是定義)的變量和函數(shù)都是外部的。但對于作用域范圍之外的變量和函數(shù),需要使用extern進(jìn)行引用性聲明。對外部變量的聲明,只是聲明該變量是在外部定義過的一個全局變量,在這里引用。而對外部變量的定義,則是要分配存儲單元。一個全局變量只能定義一次,卻可以多次引用。用extern聲明外部變量的目的是可以在其他的文件中調(diào)用。5.6.3變量的存儲類型5.6變量的作用域和存儲類型【案例5-6】靜態(tài)變量示例。打開源程序程序運(yùn)行結(jié)果5.6變量的作用域和存儲類型【案例5-7】外部變量和外部函數(shù)示例。打開源程序程序運(yùn)行結(jié)果5.7編譯預(yù)處理C程序的編譯可分成編譯預(yù)處理和正式編譯兩個步驟。在編譯C源程序時,系統(tǒng)將自動調(diào)用編譯預(yù)處理程序,根據(jù)編譯預(yù)處理命令對程序進(jìn)行適當(dāng)?shù)募庸?,處理完畢自動進(jìn)入對源程序的正式編譯。預(yù)處理是C語言的一個重要功能,它由預(yù)處理程序負(fù)責(zé)完成。C語言提供了多種預(yù)處理功能,如宏定義、文件包含和條件編譯等。預(yù)處理有以下幾個特點(diǎn)。(1)預(yù)處理命令均以#開頭,結(jié)尾不加分號。(2)預(yù)處理命令可以放在程序中任何位置,作用范圍從定義到文件結(jié)尾。5.7編譯預(yù)處理宏定義是用一個標(biāo)識符(又稱宏名)定義為一個字符串(又稱宏體)。在編譯預(yù)處理時,對程序中所有在宏定義中定義的標(biāo)識符,都用宏定義中的相應(yīng)字符串替換,稱為“宏替換”或“宏展開”。C語言的宏定義分為兩種:一種是簡單宏定義,即不帶參數(shù)的宏定義;另一種是復(fù)雜的宏定義,即帶參數(shù)的宏定義(有參宏定義)。
1.不帶參數(shù)的宏定義不帶參數(shù)宏定義的一般形式如下:其中,#define是宏定義的命令,標(biāo)識符和字符串之間用空格分開。標(biāo)識符稱為“宏名”,字符串又稱為宏體。功能:在程序中凡出現(xiàn)該標(biāo)識符(宏名)的位置,經(jīng)編譯預(yù)處理的加工,都被替換成對應(yīng)的宏體字符串,稱之為“宏展開”。例如:#definePI3.1415926/*定義PI為一個宏,其值為3.1415926*/5.7.1宏定義#define
標(biāo)識符字符串5.7編譯預(yù)處理關(guān)于宏的幾點(diǎn)說明如下。(1)使用宏名代替一個字符串,可以減少程序中重復(fù)書寫某些字符串的工作量,增加程序的可讀性,而且不易出錯。(2)宏定義命令行放在源程序的函數(shù)外時,宏名的作用域從宏定義命令行開始到本源文件結(jié)束。(3)宏名的作用域可以使用#undef命令終止,形式如下:在#define語句定義了該宏之后,到#undef命令之前的程序中,該宏定義都有效,但在#undef命令后該宏則無效了。(4)C語言中,用宏名替換一個字符串是簡單的轉(zhuǎn)換過程,不作語法檢查。若將宏體的字符串中符號寫錯了,宏展開時照樣代入,只有在編譯宏展開后的源程序時才會提示語法錯誤。例如:#definePI3.141592B/*定義PI為一個宏,其值為3.141592B,值出錯*/預(yù)處理時照樣替換,而不管其含義是否正確,一直到對宏展開的結(jié)果進(jìn)行編譯時,才會產(chǎn)生錯誤提示。5.7.1宏定義#undef
標(biāo)識符5.7編譯預(yù)處理(5)一個宏名只能被定義一次,否則會出現(xiàn)重復(fù)定義的錯誤。(6)宏定義可以嵌套。在宏體中,可以出現(xiàn)已定義的宏名,例如:#definePI3.1415926#definePIR(PI*r) /*PI為已定義的宏名*/(7)如果宏定義一行書寫不下,可用反斜線“\”和回車鍵來結(jié)束本行,然后在下一行繼續(xù)書寫。例如,有如下程序:#defineSTR"Hello,\alltheworldpeople!"main(){printf("%s\n",STR);}運(yùn)行程序?qū)⑤敵觯篐ello,alltheworldpeople!(8)程序中出現(xiàn)的由雙引號括起來的字符串,即使和宏名相同,也不進(jìn)行宏替換。例如,在輸出函數(shù)printf()中如果在雙引號內(nèi)有與宏名相同的字符串,也不認(rèn)為是宏,只認(rèn)為是普通字符串原樣輸出。5.7.1宏定義5.7編譯預(yù)處理2.帶參數(shù)的宏定義帶參數(shù)宏定義的一般格式如下:其中,#define是宏定義的命令,標(biāo)識符后的圓括號內(nèi)為形參表,后面形參表達(dá)式為圓括號內(nèi)的各形參構(gòu)成的表達(dá)式。例如:#defineMAX(a,b)(a>b)?(a):(b)/*定義了一個帶參數(shù)的宏MAX,有兩個參數(shù)a、b,其功能是求a和b中較大值*/帶參數(shù)的宏的調(diào)用格式如下:進(jìn)行宏替換時,可以像使用函數(shù)一樣,通過實(shí)參與形參傳遞數(shù)據(jù)。帶參數(shù)的宏展開是用宏調(diào)用提供的實(shí)參字符串,直接置換宏定義命令行中相應(yīng)形參字符串,非形參字符保持不變。5.7.1宏定義#define
標(biāo)識符(形參表)形參表達(dá)式標(biāo)識符(實(shí)參表)5.7編譯預(yù)處理帶參數(shù)的宏展開時要注意以下兩點(diǎn)。(1)帶參數(shù)的宏展開是按#define命令行中指定的字符串從左到右進(jìn)行置換。(2)如果宏體字符串中包含宏名中的形參,則將程序語句中相應(yīng)的實(shí)參代替形參,如果字符串中的字符不是參數(shù)字符,則保留。例如,在主函數(shù)中有如下語句:intx=3,y=5,m;m=MAX(x*2,y*3);/*使用帶參數(shù)的宏,可以進(jìn)行宏替換*/則替換后相當(dāng)于:m=(x*2>y*3)?(x*2):(y*3);/*替換時將x*2替換形參表達(dá)式中的a,將y*3替換b*/5.7.1宏定義5.7編譯預(yù)處理帶參數(shù)的宏定義的幾點(diǎn)說明如下。(1)定義有參數(shù)的宏時,宏名應(yīng)當(dāng)與參數(shù)表的左括號緊緊相連。否則,C編譯系統(tǒng)將空格以后的所有字符均作為替代字符串,而將該宏視為無參宏。(2)宏定義時,應(yīng)將整個字符串以及其中的各個參數(shù)均用圓括號括起來,以確保宏展開后字符串中各個參數(shù)的計算順序的正確性,避免出現(xiàn)錯誤。例如,宏定義為:#defineS(a,b)a*b在程序中遇到如下語句:m=S(a+1,b+1)*c;對其進(jìn)行宏展開如下:m=a+1*b+1*c;5.7.1宏定義5.7編譯預(yù)處理此時表達(dá)式變?yōu)閍+b+c,這與想要的((a+1)*(b+1))*c不同,所以出錯??蓪⒚總€參數(shù)和整個字符串都用括號括起來,改為以下宏定義:#defineS(a,b)((a)*(b))再對以上語句進(jìn)行宏展開,結(jié)果如下:m=((a+1)*(b+1))*c;這正是想要的結(jié)果。(3)在宏定義中的形參是標(biāo)識符,而宏展開的實(shí)參可以是表達(dá)式。例如上面的語句:m=S(a+1,b+1)*c;在宏調(diào)用的語句S(a+1,b+1)中表達(dá)式a+1和b+1為S的兩個實(shí)參。5.7.1宏定義5.7編譯預(yù)處理【案例5-8】設(shè)計一個程序,從3個數(shù)中找最大數(shù),用帶參數(shù)的宏定義實(shí)現(xiàn)。程序分析:因?yàn)闂l件語句可以通過一條語句實(shí)現(xiàn)求3個數(shù)中最大值的功能,該語句為:a>b?(a>c?a:c):(b>c?b:c)因?yàn)閹?shù)的宏定義在宏替換時是將實(shí)參的表達(dá)式替換到每個形參位置,所以將a、b、c三個形參和整個表達(dá)式都括起來,防止出現(xiàn)替換錯誤。所以可以設(shè)一個帶3個參數(shù)的宏定義,宏的值用一個條件語句來實(shí)現(xiàn)。打開源程序程序運(yùn)行結(jié)果:5.7編譯預(yù)處理一個大程序,通常分為多個模塊,并由多個程序員分別編程。有了文件包含處理功能,就可以將多個模塊共用的數(shù)據(jù)(如符號常量和數(shù)據(jù)結(jié)構(gòu))或函數(shù),集中到一個單獨(dú)的文件中。這樣,凡是要使用其中數(shù)據(jù)或調(diào)用其中函數(shù)的程序員,只要使用文件包含處理功能,將所需文件包含進(jìn)來即可,不必再重復(fù)定義它們,從而減少重復(fù)勞動。
1.文件包含命令的兩種格式文件包含功能是把指定的一個源文件的全部內(nèi)容插入到源程序該命令行。文件包含命令格式主要有以下兩種。(1)只檢索C語言編譯系統(tǒng)所確定的標(biāo)準(zhǔn)目錄,格式如下:(2)首先對使用包含文件的源文件所在的目錄進(jìn)行檢索,若沒有找到指定的文件,再在標(biāo)準(zhǔn)目錄中檢索,格式如下:5.7.2文件包含#include<文件名>#include
"文件名"5.7編譯預(yù)處理2.文件包含命令幾點(diǎn)說明(1)編譯預(yù)處理時,預(yù)處理程序?qū)⒉檎抑付ǖ谋话募⑵鋸?fù)制到#include命令出現(xiàn)的位置上。(2)常用在文件頭部的被包含文件,稱為“標(biāo)題文件”或“頭部文件”,常以“h”(head)作為后綴,簡稱頭文件。在頭文件中,除可包含宏定義外,還可包含外部變量定義、結(jié)構(gòu)類型定義等。(3)一條包含命令,只能指定一個被包含文件。如果要包含n個文件,則要用n條包含命令。(4)文件包含可以嵌套,即被包含文件中又包含另一個文件。5.7.2文件包含5.7編譯預(yù)處理所謂條件編譯,是指對源程序進(jìn)行選擇性編譯。通常情況下,C語言程序的所有程序行都需要進(jìn)行編譯,但有時可能希望程序的某個程序段在滿足一定條件時才決定進(jìn)行編譯或不進(jìn)行編譯。使用條件編譯功能,為程序的調(diào)試和移植提供了有力的機(jī)制,使程序可以適應(yīng)不同系統(tǒng)和硬件設(shè)置的通用性和靈活性。常用條件編譯有以下兩種形式,下面分別介紹。
1.#ifdef命令(或#ifndef命令)#ifdef(或#ifndef)命令的一般格式如下5.7.3條件編譯#ifdef標(biāo)識符
#ifndef標(biāo)識符
程序段1 程序段1[#else或
[#else
程序段2] 程序段2]#endif #endif5.7編譯預(yù)處理2.#if命令#if命令一般格式如下:功能:#if命令的功能是當(dāng)表達(dá)式為非0(“邏輯真”)時,編譯程序段1,否則編譯程序段2。3.條件編譯和if語句的區(qū)別。(1)if語句控制某些語句是否被執(zhí)行,#if命令控制著某個程序段是否被編譯。(2)用if語句調(diào)試程序成功后,其調(diào)試語句仍被編譯成目標(biāo)代碼,只是不再執(zhí)行,成為廢碼。而使用條件編譯調(diào)試程序成功后,其調(diào)試語句不再被編譯,不生成目標(biāo)代碼,沒有廢碼產(chǎn)生,空間利用率較高。5.7.3條件編譯#if常量表達(dá)式
程序段1 [#else
程序段2]#endif 5.7編譯預(yù)處理【案例5-9】輸入一行字母字符串,根據(jù)需要設(shè)置條件編譯,使之能將字母全改為大寫輸出,或全改為小寫字母輸出。程序分析:定義一個常量LETTER,通過判斷LETTER的值來對某些程序進(jìn)行條件編譯。當(dāng)LETTER已經(jīng)被定義過時將字符串str中的全部字符轉(zhuǎn)換成大寫字母,沒有定義過LETTER時將大寫字母轉(zhuǎn)換成小些字母。注意條件編譯的語句格式。打開源程序調(diào)試運(yùn)行程序:將宏定義:#defineLETTER1加上或去掉,程序運(yùn)行結(jié)果分別如下:5.8
程序案例【案例5-10】編寫函數(shù)求x的n次冪。打開源程序程序運(yùn)行結(jié)果9/22/20235.8.1典型案例——編寫函數(shù)實(shí)現(xiàn)求xn5.8
程序案例【案例5-11】設(shè)計遞歸函數(shù)gcd(x,y),求x和y的最大公約數(shù)。打開源程序程序運(yùn)行結(jié)果5.8.2典型案例——設(shè)計遞歸函數(shù)gcd(x,y),求x和y的最大公約數(shù)5.8
程序案例【案例5-12】設(shè)計函數(shù)even,驗(yàn)證任意偶數(shù)為兩個素數(shù)之和,輸出這兩個素數(shù)。打開源程序程序運(yùn)行結(jié)果5.8.3典型案例——設(shè)計函數(shù)驗(yàn)證任意偶數(shù)為兩個素數(shù)之和5.8
程序案例【案例5-13】編寫函數(shù)實(shí)現(xiàn)將一個無符號整數(shù)轉(zhuǎn)換為任意d進(jìn)制數(shù)(2≤d≤16)。打開源程序程序運(yùn)行結(jié)果5.8.4典型案例——編寫函數(shù)實(shí)現(xiàn)任意進(jìn)制數(shù)的轉(zhuǎn)換本章小結(jié)本章著重介紹了函數(shù)的定義、函數(shù)的調(diào)用和函數(shù)聲明;遞歸函數(shù)的定義及調(diào)用;函數(shù)與函數(shù)之間的數(shù)據(jù)傳遞。同時還介紹了模塊化的程序設(shè)計及C源程序基本結(jié)構(gòu);變量及函數(shù)的作用域和存儲類型。C語言函數(shù)有兩種,一種是由系統(tǒng)提供的標(biāo)準(zhǔn)函數(shù),這種函數(shù)用戶可以直接使用;另一種是用戶自定義的函數(shù),這種函數(shù)用戶必須先定義后使用。在對函數(shù)進(jìn)行定義時,有返回值的函數(shù)必須用“return表達(dá)式;”結(jié)束函數(shù)的運(yùn)行;若函數(shù)是以“return;”結(jié)束運(yùn)行的,說明該函數(shù)是無返回值函數(shù)。函數(shù)聲明是提供函數(shù)調(diào)用接口信息的說明形式,其格式就是在函數(shù)定義格式的基礎(chǔ)上去掉了函數(shù)體,可見函數(shù)定義涵蓋函數(shù)聲明,同樣能提供有關(guān)的接口信息。本章小結(jié)函數(shù)可以作為表達(dá)式調(diào)用,也可以作為語句調(diào)用。函數(shù)調(diào)用時通常以傳值的方式傳遞參數(shù),改動形參變量的值不會影響對應(yīng)實(shí)參變量。定義于函數(shù)外的變量稱為全局變量,用static修飾的全局變量只允許被本文件中的函數(shù)訪問,而沒有用static修飾的全局變量則允許同一程序任何文件中的函數(shù)訪問。定義于函數(shù)內(nèi)的變量稱為局部變量
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024高考化學(xué)一輪復(fù)習(xí)專練14鐵銅及其化合物含解析新人教版
- 2024高考化學(xué)一輪復(fù)習(xí)第一部分考點(diǎn)13化學(xué)與可持續(xù)發(fā)展強(qiáng)化訓(xùn)練含解析
- 2024高考化學(xué)一輪復(fù)習(xí)第四章非金屬及其化合物第二講富集在海水中的元素-氯規(guī)范演練含解析新人教版
- 2024高考?xì)v史一輪復(fù)習(xí)模塊四選修部分第1講歷史上重大改革回眸學(xué)案含解析人民版
- 學(xué)校視頻監(jiān)控配置情況匯報
- 鋼結(jié)構(gòu)廠房工程施工要點(diǎn)
- 2024年湖北三峽職業(yè)技術(shù)學(xué)院高職單招語文歷年參考題庫含答案解析
- 平安福產(chǎn)說會修正版
- 八年級物理下冊121杠桿課件新版新人教版
- 二零二五年度高校畢業(yè)生就業(yè)見習(xí)實(shí)習(xí)實(shí)訓(xùn)基地安全管理合同3篇
- 資質(zhì)模型與測評技術(shù)(中國人民大學(xué)勞動人事學(xué)院 孫健敏)
- SMW工法型鋼拔除專項(xiàng)施工方案
- 大健康商業(yè)招商計劃書
- 高一上半學(xué)期總結(jié)教學(xué)課件
- 高速公路初步設(shè)計匯報課件
- 申根簽證申請表模板
- 企業(yè)會計準(zhǔn)則、應(yīng)用指南及附錄2023年8月
- 2022年浙江省事業(yè)編制招聘考試《計算機(jī)專業(yè)基礎(chǔ)知識》真題試卷【1000題】
- 認(rèn)養(yǎng)一頭牛IPO上市招股書
- GB/T 3767-2016聲學(xué)聲壓法測定噪聲源聲功率級和聲能量級反射面上方近似自由場的工程法
- GB/T 23574-2009金屬切削機(jī)床油霧濃度的測量方法
評論
0/150
提交評論