C語言程序設計_06函數(shù)與編譯預處理_第1頁
C語言程序設計_06函數(shù)與編譯預處理_第2頁
C語言程序設計_06函數(shù)與編譯預處理_第3頁
C語言程序設計_06函數(shù)與編譯預處理_第4頁
C語言程序設計_06函數(shù)與編譯預處理_第5頁
已閱讀5頁,還剩49頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、第第6章章 函數(shù)與編譯預處理函數(shù)與編譯預處理6.1 C程序的模塊結構程序的模塊結構6.2 函數(shù)的定義與調用函數(shù)的定義與調用6.3 函數(shù)的參數(shù)傳遞函數(shù)的參數(shù)傳遞6.4 函數(shù)的嵌套調用與遞歸調用函數(shù)的嵌套調用與遞歸調用6.5 變量的作用域與存儲類別變量的作用域與存儲類別6.6 內部函數(shù)和外部函數(shù)內部函數(shù)和外部函數(shù)6.7 函數(shù)應用舉例函數(shù)應用舉例6.8 編譯預處理編譯預處理本章小結本章小結6.1 C程序的模塊結構程序的模塊結構一個用一個用C語言開發(fā)的軟件往往由許多功能模塊組成,各語言開發(fā)的軟件往往由許多功能模塊組成,各個功能模塊彼此有一定的聯(lián)系,功能上各自獨立。在個功能模塊彼此有一定的聯(lián)系,功能上各

2、自獨立。在C語言中,用函數(shù)來實現(xiàn)功能模塊的定義。通常一個具語言中,用函數(shù)來實現(xiàn)功能模塊的定義。通常一個具有一定規(guī)模的有一定規(guī)模的C程序往往由多個函數(shù)組成。其中有且僅程序往往由多個函數(shù)組成。其中有且僅有一個主函數(shù),由主函數(shù)來調用其他函數(shù)。如圖有一個主函數(shù),由主函數(shù)來調用其他函數(shù)。如圖6-1所所示是一個程序中函數(shù)調用的示意圖。示是一個程序中函數(shù)調用的示意圖。 圖圖6-1 C語言程序的模塊語言程序的模塊結構結構C語言中,函數(shù)可按多種方式來分類:語言中,函數(shù)可按多種方式來分類:(1)從使用的角度來分,可以分為標準函數(shù)和用戶函數(shù)。)從使用的角度來分,可以分為標準函數(shù)和用戶函數(shù)。(2)從形式上來分,可以分

3、為無參函數(shù)和有參函數(shù)。)從形式上來分,可以分為無參函數(shù)和有參函數(shù)。(3)從作用范圍來分,可以分為外部函數(shù)和內部函數(shù)。)從作用范圍來分,可以分為外部函數(shù)和內部函數(shù)。(4)從返回值來分,可以分為無返回值函數(shù)和有返回值函)從返回值來分,可以分為無返回值函數(shù)和有返回值函數(shù)。數(shù)。6.2 函數(shù)的定義與調用函數(shù)的定義與調用6.2.1 函數(shù)的定義函數(shù)的定義C語言函數(shù)的定義包括對函數(shù)名、函數(shù)的參數(shù)、函數(shù)返回值語言函數(shù)的定義包括對函數(shù)名、函數(shù)的參數(shù)、函數(shù)返回值的類型與函數(shù)功能的描述。的類型與函數(shù)功能的描述。 一般形式為:一般形式為:類型符 函數(shù)名(形式參數(shù)說明) 聲明與定義部分 語句部分1函數(shù)首部函數(shù)首部函數(shù)首部

4、用于對函數(shù)的特征進行定義。類型符用于標識函數(shù)函數(shù)首部用于對函數(shù)的特征進行定義。類型符用于標識函數(shù)返回值的類型。當函數(shù)不返回值時,習慣用返回值的類型。當函數(shù)不返回值時,習慣用VOID來標記。來標記。另外,當函數(shù)返回另外,當函數(shù)返回INT型值時,類型符型值時,類型符INT可以省略??梢允÷?。函數(shù)名是一個標識符,在函數(shù)定義中,函數(shù)名后括號內的形函數(shù)名是一個標識符,在函數(shù)定義中,函數(shù)名后括號內的形式參數(shù)(式參數(shù)(FORMAL PARAMETER)是按需要而設定的,也)是按需要而設定的,也可以沒有形式參數(shù),但函數(shù)名后一對圓括號必須保留。形式可以沒有形式參數(shù),但函數(shù)名后一對圓括號必須保留。形式參數(shù)簡稱形參

5、。參數(shù)簡稱形參。當函數(shù)有形參時,在形參表中,除給出形參名外,還要指出當函數(shù)有形參時,在形參表中,除給出形參名外,還要指出它的類型。一般形式為:它的類型。一般形式為:類型符 形參名1,類型符 形參名2,類型符 形參名N2函數(shù)體函數(shù)體在函數(shù)定義的最外層花括號括起來的部分稱作函數(shù)體。在函在函數(shù)定義的最外層花括號括起來的部分稱作函數(shù)體。在函數(shù)體的前面部分可以包含函數(shù)體中程序對象的聲明和變量定數(shù)體的前面部分可以包含函數(shù)體中程序對象的聲明和變量定義,聲明和定義之后是描述函數(shù)功能的語句部分。義,聲明和定義之后是描述函數(shù)功能的語句部分。函數(shù)體中的函數(shù)體中的RETURN語句用于傳遞函數(shù)的返回值。一般格式語句用于

6、傳遞函數(shù)的返回值。一般格式為:為:RETURN 表達式;說明:說明:(1)一個函數(shù)中可以有多個)一個函數(shù)中可以有多個RETURN語句,當執(zhí)行到某個語句,當執(zhí)行到某個RETURN語句時,程序的控制流程返回調用函數(shù),并將語句時,程序的控制流程返回調用函數(shù),并將RETURN語句中表達式的值作為函數(shù)值帶回。語句中表達式的值作為函數(shù)值帶回。(2)若函數(shù)體內沒有)若函數(shù)體內沒有RETURN語句,就一直執(zhí)行到函數(shù)體語句,就一直執(zhí)行到函數(shù)體的末尾,然后返回調用函數(shù)。這時也有一個不確定的函數(shù)值的末尾,然后返回調用函數(shù)。這時也有一個不確定的函數(shù)值被帶回。被帶回。(3)若不需要帶回函數(shù)值,一般將函數(shù)定義為)若不需要

7、帶回函數(shù)值,一般將函數(shù)定義為VOID類型。類型。(4)RETURN語句中表達式的類型應與函數(shù)返回值的類型語句中表達式的類型應與函數(shù)返回值的類型一致。不一致時,以函數(shù)返回值的類型為準。一致。不一致時,以函數(shù)返回值的類型為準。3空函數(shù)空函數(shù)C語言還允許函數(shù)體為空的函數(shù),其形式為:語言還允許函數(shù)體為空的函數(shù),其形式為:函數(shù)名() 調用此函數(shù)時,什么工作也不做。調用此函數(shù)時,什么工作也不做。6.2.2 函數(shù)的調用函數(shù)的調用函數(shù)調用的一般形式為:函數(shù)調用的一般形式為:函數(shù)名(實在參數(shù)表)當有多個實在參數(shù)(當有多個實在參數(shù)(ACTUAL PARAMETER)時,實在參)時,實在參數(shù)之間用逗號分隔。數(shù)之間用

8、逗號分隔。如果調用的是無參數(shù)函數(shù),則調用形式為:如果調用的是無參數(shù)函數(shù),則調用形式為:函數(shù)名()其中函數(shù)名之后的一對括號不能省略。其中函數(shù)名之后的一對括號不能省略。函數(shù)調用時提供的實在參數(shù)(簡稱實參)應與被調用函數(shù)的函數(shù)調用時提供的實在參數(shù)(簡稱實參)應與被調用函數(shù)的形式參數(shù)按順序一一對應,而且參數(shù)類型要一致。形式參數(shù)按順序一一對應,而且參數(shù)類型要一致。按調用函數(shù)在程序中的作用不同,有兩種不同的應用方式:按調用函數(shù)在程序中的作用不同,有兩種不同的應用方式:(1)將函數(shù)調用作為一個獨立的語句。如前面例子中經(jīng)常)將函數(shù)調用作為一個獨立的語句。如前面例子中經(jīng)常使用的輸入輸出函數(shù)調用。這種應用情況不要

9、求或無視函數(shù)使用的輸入輸出函數(shù)調用。這種應用情況不要求或無視函數(shù)的返回值,需要的只是函數(shù)完成的操作。的返回值,需要的只是函數(shù)完成的操作。(2)函數(shù)調用作為表達式中的一個運算量。這種應用情況)函數(shù)調用作為表達式中的一個運算量。這種應用情況要求函數(shù)調用能返回一個值,參與表達式的計算。要求函數(shù)調用能返回一個值,參與表達式的計算?!纠?.1】求五邊形面積,長度求五邊形面積,長度L1L7從鍵盤輸入。從鍵盤輸入。6.2.3 對被調用函數(shù)的聲明和函數(shù)原型對被調用函數(shù)的聲明和函數(shù)原型1函數(shù)的聲明函數(shù)的聲明一般被調用函數(shù)應放在調用函數(shù)之前定義。若被調用函數(shù)的一般被調用函數(shù)應放在調用函數(shù)之前定義。若被調用函數(shù)的

10、定義在調用函數(shù)之后出現(xiàn),就必須在調用函數(shù)中對被調用函定義在調用函數(shù)之后出現(xiàn),就必須在調用函數(shù)中對被調用函數(shù)加以聲明,函數(shù)聲明的一般形式為:數(shù)加以聲明,函數(shù)聲明的一般形式為:類型符 函數(shù)名(形參類型1 形參名1,形參類型2 形參名2,);這種形式的函數(shù)聲明只是對已定義的函數(shù)名及其返回值的類這種形式的函數(shù)聲明只是對已定義的函數(shù)名及其返回值的類型、參數(shù)個數(shù)及參數(shù)類型作聲明,以便讓編譯程序預先知道型、參數(shù)個數(shù)及參數(shù)類型作聲明,以便讓編譯程序預先知道該標識符是函數(shù)和函數(shù)返回值的類型,為該函數(shù)的調用編譯該標識符是函數(shù)和函數(shù)返回值的類型,為該函數(shù)的調用編譯出正確的目標代碼。出正確的目標代碼。注意:函數(shù)的聲明

11、和函數(shù)的定義形式上類似,但兩者有本注意:函數(shù)的聲明和函數(shù)的定義形式上類似,但兩者有本質的不同。主要區(qū)別在以下幾方面。質的不同。主要區(qū)別在以下幾方面。(1)函數(shù)的定義()函數(shù)的定義(DEFINITION)是編寫一段程序,除)是編寫一段程序,除上面內容之外,應有函數(shù)具體的功能語句,即函數(shù)體,而上面內容之外,應有函數(shù)具體的功能語句,即函數(shù)體,而函數(shù)的聲明(函數(shù)的聲明(DECLARATION)僅是對編譯系統(tǒng)的一個)僅是對編譯系統(tǒng)的一個說明,不含具體的執(zhí)行動作。說明,不含具體的執(zhí)行動作。(2)在程序中,函數(shù)的定義只能有一次,而函數(shù)的聲明)在程序中,函數(shù)的定義只能有一次,而函數(shù)的聲明可以有多次,有多少個主

12、調函數(shù)要調用該被調函數(shù),就應可以有多次,有多少個主調函數(shù)要調用該被調函數(shù),就應在各個主調函數(shù)中各自進行聲明。在各個主調函數(shù)中各自進行聲明。【例例6.2】計算并輸出計算并輸出Y的值。的值。以下幾種情況下,可省略函數(shù)聲明:以下幾種情況下,可省略函數(shù)聲明:(1)如果被調用函數(shù)的定義出現(xiàn)在調用它之前,根據(jù))如果被調用函數(shù)的定義出現(xiàn)在調用它之前,根據(jù)C語言語言的定義隱含著聲明原則,可以不必對被調用函數(shù)作聲明。例的定義隱含著聲明原則,可以不必對被調用函數(shù)作聲明。例6.1即是這種情況。即是這種情況。(2)如被調用函數(shù)的返回值是整型或字符型,也可以不對)如被調用函數(shù)的返回值是整型或字符型,也可以不對它作聲明。

13、因編譯系統(tǒng)發(fā)現(xiàn)程序調用一個還未被定義或聲明它作聲明。因編譯系統(tǒng)發(fā)現(xiàn)程序調用一個還未被定義或聲明的函數(shù)時,就假定它的返回值是整型的,而字符型又是與整的函數(shù)時,就假定它的返回值是整型的,而字符型又是與整型相通的。型相通的。 (3)如果被調用函數(shù)的聲明已出現(xiàn)在函數(shù)定義之前(特別)如果被調用函數(shù)的聲明已出現(xiàn)在函數(shù)定義之前(特別是在程序文件的開頭處),則位于該函數(shù)聲明之后定義的所是在程序文件的開頭處),則位于該函數(shù)聲明之后定義的所有函數(shù)都可調用該函數(shù),而不必另加聲明。有函數(shù)都可調用該函數(shù),而不必另加聲明。除以上除以上3種情況外,包括調用另一個源程序文件中定義的函種情況外,包括調用另一個源程序文件中定義的

14、函數(shù),都應對被調用函數(shù)在調用它之前作聲明。數(shù),都應對被調用函數(shù)在調用它之前作聲明。2函數(shù)原型的概念函數(shù)原型的概念在對被調函數(shù)的聲明時,編譯系統(tǒng)需知道被調函數(shù)有幾個參在對被調函數(shù)的聲明時,編譯系統(tǒng)需知道被調函數(shù)有幾個參數(shù),各自是什么類型,而參數(shù)的名字是無關緊要的,因此,數(shù),各自是什么類型,而參數(shù)的名字是無關緊要的,因此,對被調函數(shù)的聲明也稱為函數(shù)原型(對被調函數(shù)的聲明也稱為函數(shù)原型(PROTOTYPE),函數(shù)),函數(shù)原型也可以簡化為:原型也可以簡化為:類型符 函數(shù)名(形參類型1,形參類型2,)6.3 函數(shù)的參數(shù)傳遞函數(shù)的參數(shù)傳遞在在C語言中,實參向形參傳送數(shù)據(jù)的方式是語言中,實參向形參傳送數(shù)據(jù)的

15、方式是“值傳遞值傳遞”,即實,即實參的值傳給形參,是一種單向傳遞方式,不能由形參傳回給參的值傳給形參,是一種單向傳遞方式,不能由形參傳回給實參。在函數(shù)執(zhí)行過程中,形參的值可能被改變,但這改變實參。在函數(shù)執(zhí)行過程中,形參的值可能被改變,但這改變對原來與它對應的實參沒有影響。對原來與它對應的實參沒有影響。值傳遞的優(yōu)點在于被調用的函數(shù)不可能改變主調函數(shù)中變量值傳遞的優(yōu)點在于被調用的函數(shù)不可能改變主調函數(shù)中變量的值,而只能改變它的局部的臨時副本。這樣就可以避免被的值,而只能改變它的局部的臨時副本。這樣就可以避免被調用函數(shù)的操作對調用函數(shù)中的變量可能產(chǎn)生的副作用。調用函數(shù)的操作對調用函數(shù)中的變量可能產(chǎn)生

16、的副作用。C語言中,在值傳遞方式下,既可以在函數(shù)之間傳遞語言中,在值傳遞方式下,既可以在函數(shù)之間傳遞“變量的變量的值值”,也可以在函數(shù)之間傳遞,也可以在函數(shù)之間傳遞“變量的地址變量的地址”。【例例6.3】分析形參和實參的結合過程。分析形參和實參的結合過程。6.4 函數(shù)的嵌套調用與遞歸調用函數(shù)的嵌套調用與遞歸調用6.4.1 函數(shù)的嵌套調用函數(shù)的嵌套調用在在C語言的函數(shù)定義內不能再定義別的函數(shù),但一個函數(shù)為語言的函數(shù)定義內不能再定義別的函數(shù),但一個函數(shù)為實現(xiàn)它的功能,可以調用其他函數(shù)。實現(xiàn)它的功能,可以調用其他函數(shù)。圖圖6-4示意了函數(shù)嵌套調用關系,其中編號表示執(zhí)行控制變示意了函數(shù)嵌套調用關系,其

17、中編號表示執(zhí)行控制變化的順序。化的順序。 圖圖6-4 函數(shù)嵌套調用控制流程函數(shù)嵌套調用控制流程【例例6.4】用弦截法求方程用弦截法求方程F(X)=X3-5X2+16X-8=0的根。的根。6.4.2 函數(shù)的遞歸調用函數(shù)的遞歸調用1遞歸的基本概念遞歸的基本概念在一個程序中,若存在程序自己調用自己的現(xiàn)象就是構成了在一個程序中,若存在程序自己調用自己的現(xiàn)象就是構成了遞歸。遞歸。C語言允許函數(shù)的遞歸調用。在調用一個函數(shù)的過程語言允許函數(shù)的遞歸調用。在調用一個函數(shù)的過程中又出現(xiàn)直接或間接地調用該函數(shù)本身,稱為函數(shù)的遞歸調中又出現(xiàn)直接或間接地調用該函數(shù)本身,稱為函數(shù)的遞歸調用。如果函數(shù)用。如果函數(shù)A在執(zhí)行過

18、程中又調用函數(shù)在執(zhí)行過程中又調用函數(shù)A自己,則稱函數(shù)自己,則稱函數(shù)A為直接遞歸。如果函數(shù)為直接遞歸。如果函數(shù)A在執(zhí)行過程中先調用函數(shù)在執(zhí)行過程中先調用函數(shù)B,函數(shù),函數(shù)B在執(zhí)行過程中又調用函數(shù)在執(zhí)行過程中又調用函數(shù)A,則稱函數(shù),則稱函數(shù)A為間接遞歸。程序為間接遞歸。程序設計中常用的是直接遞歸。設計中常用的是直接遞歸。數(shù)學上遞歸定義的函數(shù)是非常多的。例如,當數(shù)學上遞歸定義的函數(shù)是非常多的。例如,當N為自然數(shù)時,為自然數(shù)時,求求N的階乘的階乘N!。2遞歸程序的執(zhí)行過程遞歸程序的執(zhí)行過程用一個簡單的遞歸程序來分析遞歸程序的執(zhí)行過程。用一個簡單的遞歸程序來分析遞歸程序的執(zhí)行過程。【例例6.5】求求N!

19、的遞歸函數(shù)。的遞歸函數(shù)。 圖圖6-6 FAC(3)的計算流程的計算流程3數(shù)值型遞歸問題的求解方法數(shù)值型遞歸問題的求解方法在掌握遞歸的基本概念和遞歸程序的執(zhí)行過程之后,還應掌在掌握遞歸的基本概念和遞歸程序的執(zhí)行過程之后,還應掌握編寫遞歸程序的基本方法。編寫遞歸程序要注意兩點,一握編寫遞歸程序的基本方法。編寫遞歸程序要注意兩點,一要找出正確的遞歸算法,這是編寫遞歸程序的基礎;二要確要找出正確的遞歸算法,這是編寫遞歸程序的基礎;二要確定算法的遞歸結束條件,這是決定遞歸程序能否正常結束的定算法的遞歸結束條件,這是決定遞歸程序能否正常結束的關鍵。關鍵?!纠?.6】用遞歸方法計算多項式函數(shù)的值。用遞歸方

20、法計算多項式函數(shù)的值。4非數(shù)值型遞歸問題的求解方法非數(shù)值型遞歸問題的求解方法對于非數(shù)值問題,編寫遞歸程序的一般方法是:確定問題的對于非數(shù)值問題,編寫遞歸程序的一般方法是:確定問題的最小模型并使用非遞歸算法解決,分解原來的非數(shù)值問題建最小模型并使用非遞歸算法解決,分解原來的非數(shù)值問題建立遞歸模型,確定遞歸模型的終止條件,將遞歸模型轉換為立遞歸模型,確定遞歸模型的終止條件,將遞歸模型轉換為遞歸程序。遞歸程序。尋找非數(shù)值問題的遞歸算法可從分析問題本身的規(guī)律入手,尋找非數(shù)值問題的遞歸算法可從分析問題本身的規(guī)律入手,按照下列步驟進行分析:按照下列步驟進行分析:(1)從化簡問題開始。將問題進行簡化,將問題

21、的規(guī)??s)從化簡問題開始。將問題進行簡化,將問題的規(guī)??s到最小,分析問題在最簡單情況下的求解方法。此時找到的到最小,分析問題在最簡單情況下的求解方法。此時找到的求解方法應當十分簡單。求解方法應當十分簡單。(2)對于一個一般的問題,可將一個大問題分解為兩個)對于一個一般的問題,可將一個大問題分解為兩個(或若干個)小問題,使原來的大問題變成這兩個(或若干(或若干個)小問題,使原來的大問題變成這兩個(或若干個)小問題的組合,其中至少有一個小問題與原來的問題有個)小問題的組合,其中至少有一個小問題與原來的問題有相同的性質,只是在問題的規(guī)模上與原來的問題相比較有所相同的性質,只是在問題的規(guī)模上與原來的問

22、題相比較有所縮小??s小。(3)將分解后的每個小問題作為一個整體,描述用這)將分解后的每個小問題作為一個整體,描述用這些較小的問題來解決原來大問題的算法。些較小的問題來解決原來大問題的算法。由第(由第(3)步得到的算法就是一個解決原來問題的遞歸)步得到的算法就是一個解決原來問題的遞歸算法。由第(算法。由第(1)步將問題的規(guī)??s到最小時的條件就)步將問題的規(guī)??s到最小時的條件就是該遞歸算法的遞歸結束條件。是該遞歸算法的遞歸結束條件?!纠?.7】利用遞歸函數(shù)打印如圖利用遞歸函數(shù)打印如圖6-7所示的數(shù)字金字塔所示的數(shù)字金字塔圖形。圖形。圖圖6-7 數(shù)字金字塔數(shù)字金字塔5關于遞歸的幾點說明關于遞歸的幾

23、點說明當一個問題蘊含了遞歸關系且結構比較復雜時,采用遞歸調當一個問題蘊含了遞歸關系且結構比較復雜時,采用遞歸調用的程序設計技巧可以使程序變得簡潔,增加了程序的可讀用的程序設計技巧可以使程序變得簡潔,增加了程序的可讀性。但遞歸調用本身是以犧牲存儲空間為基礎的,因為每一性。但遞歸調用本身是以犧牲存儲空間為基礎的,因為每一次遞歸調用都要保存相關的參數(shù)和變量。同樣,遞歸本身也次遞歸調用都要保存相關的參數(shù)和變量。同樣,遞歸本身也不會加快執(zhí)行速度;相反,由于反復調用函數(shù),還會或多或不會加快執(zhí)行速度;相反,由于反復調用函數(shù),還會或多或少地增加時間開銷。遞歸調用能使代碼緊湊,并能夠很容易少地增加時間開銷。遞歸

24、調用能使代碼緊湊,并能夠很容易地解決一些用非遞歸算法很難解決的問題。地解決一些用非遞歸算法很難解決的問題。注意:所有的遞歸問題都一定可以用非遞歸的算法實現(xiàn),并注意:所有的遞歸問題都一定可以用非遞歸的算法實現(xiàn),并且已經(jīng)有了固定的算法。如何將遞歸程序轉化為非遞歸程序且已經(jīng)有了固定的算法。如何將遞歸程序轉化為非遞歸程序的算法已經(jīng)超出了本書的范圍,感興趣的讀者可以參看有關的算法已經(jīng)超出了本書的范圍,感興趣的讀者可以參看有關數(shù)據(jù)結構的文獻資料。數(shù)據(jù)結構的文獻資料。6.5 變量的作用域與存儲類別變量的作用域與存儲類別6.5.1 變量的作用域變量的作用域在程序中能對變量進行存取操作的范圍稱為變量的作用域。在

25、程序中能對變量進行存取操作的范圍稱為變量的作用域。根據(jù)變量的作用域不同,變量分為局部變量和全局變量。根據(jù)變量的作用域不同,變量分為局部變量和全局變量。1局部變量局部變量在一個函數(shù)體內或復合語句內定義的變量稱為局部變量。局在一個函數(shù)體內或復合語句內定義的變量稱為局部變量。局部變量只在定義它的函數(shù)體或復合語句內有效,即只能在定部變量只在定義它的函數(shù)體或復合語句內有效,即只能在定義它的函數(shù)體或復合語句內部使用它,而在定義它的函數(shù)體義它的函數(shù)體或復合語句內部使用它,而在定義它的函數(shù)體或復合語句之外不能使用它?;驈秃险Z句之外不能使用它。2全局變量全局變量在函數(shù)定義之外定義的變量稱為全局變量。全局變量可以

26、在在函數(shù)定義之外定義的變量稱為全局變量。全局變量可以在定義它的文件中使用,其作用域是從它的定義處開始到變量定義它的文件中使用,其作用域是從它的定義處開始到變量所在文件的末尾。所在文件的末尾。說明:說明:(1)全局變量在程序執(zhí)行期間一直存在,一個全局變量也)全局變量在程序執(zhí)行期間一直存在,一個全局變量也可被位于它定義之前的函數(shù)使用,甚至別的源程序文件中的可被位于它定義之前的函數(shù)使用,甚至別的源程序文件中的函數(shù)使用,但需在使用之前給出外部變量的聲明(用關鍵字函數(shù)使用,但需在使用之前給出外部變量的聲明(用關鍵字EXTERN)。)。【例例6.8】寫出以下程序輸出結果。寫出以下程序輸出結果。(2)在同一

27、源文件中,如果全部變量與局部變量同名,則)在同一源文件中,如果全部變量與局部變量同名,則在局部變量的作用范圍內,全局變量不起作用。在局部變量的作用范圍內,全局變量不起作用?!纠?.9】寫出程序的輸出結果。寫出程序的輸出結果。(3)在程序中定義全局變量的主要目的是為函數(shù)間的數(shù)據(jù))在程序中定義全局變量的主要目的是為函數(shù)間的數(shù)據(jù)聯(lián)系提供一個直接傳遞的通道。在某些應用中,函數(shù)將執(zhí)行聯(lián)系提供一個直接傳遞的通道。在某些應用中,函數(shù)將執(zhí)行結果保留在全局變量中,使函數(shù)能返回多個值。在另一些應結果保留在全局變量中,使函數(shù)能返回多個值。在另一些應用中,將部分參數(shù)信息放在全局變量中,以減少函數(shù)調用時用中,將部分參

28、數(shù)信息放在全局變量中,以減少函數(shù)調用時的參數(shù)傳遞。因程序中的多個函數(shù)能使用全局變量,其中某的參數(shù)傳遞。因程序中的多個函數(shù)能使用全局變量,其中某個函數(shù)改變全局變量的值就可能會影響其他函數(shù)的執(zhí)行,產(chǎn)個函數(shù)改變全局變量的值就可能會影響其他函數(shù)的執(zhí)行,產(chǎn)生副作用。生副作用。6.5.2 變量的存儲類別變量的存儲類別變量具有可訪問性和存在性兩種基本屬性。前面介紹的變量變量具有可訪問性和存在性兩種基本屬性。前面介紹的變量作用域是指在程序的某個范圍內的所有語句都可以通過變量作用域是指在程序的某個范圍內的所有語句都可以通過變量名訪問該變量,即代表變量的可訪問性。名訪問該變量,即代表變量的可訪問性。在計算機中,保

29、存變量當前值的存儲單元有兩類:一類是內在計算機中,保存變量當前值的存儲單元有兩類:一類是內存,另一類是存,另一類是CPU中的寄存器。變量的存儲類別就是討論變中的寄存器。變量的存儲類別就是討論變量的存儲位置,量的存儲位置,C語言中定義了語言中定義了4種存儲類別,即自動種存儲類別,即自動(AUTO)變量、外部()變量、外部(EXTERN)變量、靜態(tài)()變量、靜態(tài)(STATIC)變量和寄存器(變量和寄存器(REGISTER)變量,它關系到變量在內存中)變量,它關系到變量在內存中的存放位置。的存放位置。C語言用變量的存儲類別指明變量的存在性,語言用變量的存儲類別指明變量的存在性,可分為兩大類:靜態(tài)存儲

30、和動態(tài)存儲。所謂靜態(tài)存儲是指在可分為兩大類:靜態(tài)存儲和動態(tài)存儲。所謂靜態(tài)存儲是指在程序運行期間分配固定的存儲空間,而動態(tài)存儲則是在程序程序運行期間分配固定的存儲空間,而動態(tài)存儲則是在程序運行期間根據(jù)需要動態(tài)分配存儲空間。運行期間根據(jù)需要動態(tài)分配存儲空間。變量的可訪問性與存在性在某些場合是一致的,但在有些場變量的可訪問性與存在性在某些場合是一致的,但在有些場合則不一致。存在這樣的情況,一個變量在某時刻雖然存在,合則不一致。存在這樣的情況,一個變量在某時刻雖然存在,但此時不可訪問它。但此時不可訪問它。1局部變量的存儲類別局部變量的存儲類別(1)自動變量。)自動變量。(2)局部靜態(tài)變量。)局部靜態(tài)變

31、量?!纠?.10】寫出程序的輸出結果。寫出程序的輸出結果。(3)寄存器變量。)寄存器變量。另有兩點需特別指出,其一是寄存器變量不能執(zhí)行取地址運另有兩點需特別指出,其一是寄存器變量不能執(zhí)行取地址運算(用運算符算(用運算符&);其二是寄存器變量不能是靜態(tài)變量。);其二是寄存器變量不能是靜態(tài)變量。2全局變量的存儲類別全局變量的存儲類別全局變量是在函數(shù)之外定義的變量,編譯時按靜態(tài)方式分配全局變量是在函數(shù)之外定義的變量,編譯時按靜態(tài)方式分配存儲單元。全局變量可以為程序中各個函數(shù)所引用。存儲單元。全局變量可以為程序中各個函數(shù)所引用。一個一個C程序可以由一個或多個源程序文件組成,而全局變量程序可以

32、由一個或多個源程序文件組成,而全局變量定義的作用域是從它的定義處開始到源程序文件的末尾。如定義的作用域是從它的定義處開始到源程序文件的末尾。如果在位于全局變量定義之前的函數(shù)中要引用該全局變量,需果在位于全局變量定義之前的函數(shù)中要引用該全局變量,需在引用之前對它作外部變量聲明。同樣地,如果在定義全局在引用之前對它作外部變量聲明。同樣地,如果在定義全局變量源文件之外的源文件中引用該全局變量,也需在引用之變量源文件之外的源文件中引用該全局變量,也需在引用之前對它作外部變量聲明。在變量定義之前冠以關鍵字前對它作外部變量聲明。在變量定義之前冠以關鍵字EXTERN,就聲明變量是外部變量。,就聲明變量是外部

33、變量。為了表明變量是靜態(tài)的,在變量定義時冠以關鍵字為了表明變量是靜態(tài)的,在變量定義時冠以關鍵字STATIC。在在C語言中,語言中,“靜態(tài)靜態(tài)”包含兩方面的意義。從程序對象在程序包含兩方面的意義。從程序對象在程序執(zhí)行期間的存在性來看,靜態(tài)表示該程序對象執(zhí)行期間的存在性來看,靜態(tài)表示該程序對象“永久永久”存在。存在。從程序對象可訪問或可調用來看,靜態(tài)表示該程序對象的專從程序對象可訪問或可調用來看,靜態(tài)表示該程序對象的專用特性。具體表現(xiàn)在,局部靜態(tài)變量只有定義它的函數(shù)可訪用特性。具體表現(xiàn)在,局部靜態(tài)變量只有定義它的函數(shù)可訪問,全局靜態(tài)變量只有在定義它的源文件中可訪問或可調用。問,全局靜態(tài)變量只有在定

34、義它的源文件中可訪問或可調用。6.6 內部函數(shù)和外部函數(shù)內部函數(shù)和外部函數(shù)6.6.1 內部函數(shù)內部函數(shù)內部函數(shù)又被稱為靜態(tài)函數(shù),它只能被定義它的文件中的其內部函數(shù)又被稱為靜態(tài)函數(shù),它只能被定義它的文件中的其他函數(shù)調用,而不能被其他文件中的函數(shù)調用,亦即內部函他函數(shù)調用,而不能被其他文件中的函數(shù)調用,亦即內部函數(shù)的作用范圍僅僅局限于本文件。為了定義內部函數(shù),需要數(shù)的作用范圍僅僅局限于本文件。為了定義內部函數(shù),需要使用關鍵字使用關鍵字STATIC。例如。例如:STATIC LONG FACTORIAL(INT X);此時,函數(shù)此時,函數(shù)FACTORIAL的作用范圍僅局限于定義它的文件,的作用范圍僅

35、局限于定義它的文件,而在其他源文件中不能調用此函數(shù)。如果在不同的源文件中而在其他源文件中不能調用此函數(shù)。如果在不同的源文件中存在同名的內部函數(shù),它們互不干擾。存在同名的內部函數(shù),它們互不干擾。6.6.2 外部函數(shù)外部函數(shù)因為函數(shù)與函數(shù)之間都是并列的,即函數(shù)不能嵌套定義,所因為函數(shù)與函數(shù)之間都是并列的,即函數(shù)不能嵌套定義,所以函數(shù)在本質上都具有外部性質。內部函數(shù)(靜態(tài)函數(shù))只以函數(shù)在本質上都具有外部性質。內部函數(shù)(靜態(tài)函數(shù))只能被定義它的源文件中的函數(shù)調用,而不能被其他源文件中能被定義它的源文件中的函數(shù)調用,而不能被其他源文件中的函數(shù)調用。除此之外,其余的函數(shù)既可被定義它的源文件的函數(shù)調用。除此

36、之外,其余的函數(shù)既可被定義它的源文件中的函數(shù)調用,也可以被其他源文件中的函數(shù)所調用,即其中的函數(shù)調用,也可以被其他源文件中的函數(shù)所調用,即其作用范圍不只局限于函數(shù)所在的源文件,而是整個程序的所作用范圍不只局限于函數(shù)所在的源文件,而是整個程序的所有文件。有時為了明確這種性質,可以在函數(shù)定義和調用時有文件。有時為了明確這種性質,可以在函數(shù)定義和調用時使用關鍵字使用關鍵字EXTERN,EXTERN既可用于外部函數(shù)的定義,既可用于外部函數(shù)的定義,也可用于外部函數(shù)的聲明。也可用于外部函數(shù)的聲明。6.7 函數(shù)應用舉例函數(shù)應用舉例【例例6.11】先定義函數(shù)求,然后調用該函數(shù)求。先定義函數(shù)求,然后調用該函數(shù)求

37、?!纠?.12】設計一個按分數(shù)規(guī)則進行加減法的程序。其中設計一個按分數(shù)規(guī)則進行加減法的程序。其中I=KMNL,J=LM,I、J的最大公約數(shù)為的最大公約數(shù)為1?!纠?.13】設計一個程序,求同時滿足下列兩個條件的分數(shù)設計一個程序,求同時滿足下列兩個條件的分數(shù)X的個數(shù):的個數(shù):(1)1/6X1/5。(2)X的分子分母都是素數(shù)且分母是的分子分母都是素數(shù)且分母是2位數(shù)。位數(shù)?!纠?.14】漢諾(漢諾(HANOI)塔問題。有)塔問題。有3根柱子根柱子A、B、C,A上堆放了上堆放了N個盤子,盤子大小不等,大的在下,小的在上,個盤子,盤子大小不等,大的在下,小的在上,如圖如圖6-8所示?,F(xiàn)在要求把這所

38、示?,F(xiàn)在要求把這N個盤子從個盤子從A搬到搬到C,在搬動過,在搬動過程中可以借助程中可以借助B作為中轉,每次只允許搬動一個盤子,且在作為中轉,每次只允許搬動一個盤子,且在移動過程中在移動過程中在3根柱子上都保持大盤在下,小盤在上。要求根柱子上都保持大盤在下,小盤在上。要求打印出移動的步驟。打印出移動的步驟。 A B C 圖圖6-8 漢諾塔問題漢諾塔問題6.8 編譯預處理編譯預處理C語言共有語言共有3種編譯預處理命令,即宏定義、文件包含種編譯預處理命令,即宏定義、文件包含和條件編譯。和條件編譯。6.8.1 宏定義宏定義C語言有兩種宏定義命令:帶參數(shù)的宏定義和不帶參數(shù)語言有兩種宏定義命令:帶參數(shù)的宏

39、定義和不帶參數(shù)的宏定義。的宏定義。 不帶參數(shù)的宏定義格式比較簡單,通常不帶參數(shù)的宏定義格式比較簡單,通常用來定義符號常量,其格式為:用來定義符號常量,其格式為:#DEFINE 宏名 字符序列其中宏名是一個標識符。其中宏名是一個標識符。為了和變量有所區(qū)別,習慣上定義符號常量時只使用為了和變量有所區(qū)別,習慣上定義符號常量時只使用大寫字母,但并不是非大寫不可。大寫字母,但并不是非大寫不可。使用符號常量有兩點好處:一是程序可讀性好,易于使用符號常量有兩點好處:一是程序可讀性好,易于閱讀理解;二是有利于程序的調試和修改。閱讀理解;二是有利于程序的調試和修改。在定義宏時還可以加上參數(shù),這就構成了帶參數(shù)的宏

40、:在定義宏時還可以加上參數(shù),這就構成了帶參數(shù)的宏:#DEFINE 宏名(參數(shù)表) 帶有參數(shù)的字符序列帶參數(shù)的宏和函數(shù)之間有以下的區(qū)別:帶參數(shù)的宏和函數(shù)之間有以下的區(qū)別:(1)函數(shù)調用時先求實參表達式的值,再傳給形參。而帶)函數(shù)調用時先求實參表達式的值,再傳給形參。而帶參數(shù)的宏只是簡單的字符替換,宏展開時并不對實參表達式參數(shù)的宏只是簡單的字符替換,宏展開時并不對實參表達式求值。函數(shù)調用時臨時分配存儲單元,宏替換并不分配存儲求值。函數(shù)調用時臨時分配存儲單元,宏替換并不分配存儲單元,也沒有返回值。單元,也沒有返回值。(2)宏比函數(shù)快。宏替換只占編譯時間,不占運行時間。)宏比函數(shù)快。宏替換只占編譯時間

41、,不占運行時間。但函數(shù)調用時分配存儲單元、傳值、返回值時都占時間。但函數(shù)調用時分配存儲單元、傳值、返回值時都占時間。(3)使用宏的程序代碼較長,因為宏在程序中存在了多次,)使用宏的程序代碼較長,因為宏在程序中存在了多次,而使用函數(shù)時,雖然多次調用,但函數(shù)代碼只存在一次。而使用函數(shù)時,雖然多次調用,但函數(shù)代碼只存在一次。(4)宏調用與宏定義之間可以不考慮參數(shù)的類型,而函數(shù))宏調用與宏定義之間可以不考慮參數(shù)的類型,而函數(shù)調用對實參有類型要求。調用對實參有類型要求。(5)一般情況下,調用函數(shù)只能得到一個返回值,而用宏)一般情況下,調用函數(shù)只能得到一個返回值,而用宏可以設法得到幾個結果??梢栽O法得到幾

42、個結果。6.8.2 文件包含文件包含所謂文件包含是指將另一個源程序文件嵌入到正在進所謂文件包含是指將另一個源程序文件嵌入到正在進行編譯預處理的源程序中的相應位置上。文件包含命行編譯預處理的源程序中的相應位置上。文件包含命令的格式為:令的格式為:#INCLUDE 或者:或者:#INCLUDE “文件名”其中文件名是指被嵌入的源程序文件的文件名,必須其中文件名是指被嵌入的源程序文件的文件名,必須用雙引號或者尖括號括起來。用雙引號或者尖括號括起來?!纠?.15】設有文件設有文件FORMAT.H:#DEFINE PR PRINTF#DEFINE NL “N”#DEFINE F “%6.3F”#DEF

43、INE F1 F NL#DEFINE F2 F F NL#DEFINE F3 F F F NL寫出下列程序的執(zhí)行結果。寫出下列程序的執(zhí)行結果。6.8.3 條件編譯條件編譯條件編譯是指根據(jù)條件對條件編譯是指根據(jù)條件對C程序的部分語句進行編譯,程序的部分語句進行編譯,其他語句不編譯。條件編譯命令有其他語句不編譯。條件編譯命令有3種形式。種形式。形式形式1:#IFDEF 標識符 程序段1 #ELSE 程序段2#ENDIF其作用是當標識符已被定義(常用宏定義),則對程其作用是當標識符已被定義(常用宏定義),則對程序段序段1進行編譯,否則對程序段進行編譯,否則對程序段2進行編譯。其中如果進行編譯。其中如

44、果程序段程序段2為空,為空,#ELSE部分可以省略。部分可以省略。這里的程序段可以是任何這里的程序段可以是任何C代碼行,也可以包含預處理命令代碼行,也可以包含預處理命令行。其中的標識符只要求已定義與否,與標識符被定義成什行。其中的標識符只要求已定義與否,與標識符被定義成什么無關。如標識符只用于這個目的,常用以下形式的宏定義么無關。如標識符只用于這個目的,常用以下形式的宏定義來定義這類標識符:來定義這類標識符:#DEFINE 標識符即標識符之后為空,直接以換行結束該宏定義命令。即標識符之后為空,直接以換行結束該宏定義命令。形式形式2:#IFNDEF 標識符 程序段1#ELSE 程序段2 #END

45、IF與形式與形式1的條件編譯命令的唯一差異是第一行的的條件編譯命令的唯一差異是第一行的IFDEF改為改為IFNDEF。其作用是當標識符未被定義時,編譯程序段。其作用是當標識符未被定義時,編譯程序段1,否,否則編譯程序段則編譯程序段2。形式形式3:#IF 表達式 程序段1 #ELSE 程序段2#ENDIF其中表達式為常量表達式,其作用是當指定的表達式值為非其中表達式為常量表達式,其作用是當指定的表達式值為非零時,編譯程序段零時,編譯程序段1,否則編譯程序段,否則編譯程序段2。條件編譯預處理命令可以嵌套。特別是為了便于描述條件編譯預處理命令可以嵌套。特別是為了便于描述#ELSE后的程序段又是條件編

46、譯情況,引入預處理命后的程序段又是條件編譯情況,引入預處理命令符令符#ELIF。它的意思就是。它的意思就是#ELSE #IF。所以條件編譯。所以條件編譯預處命令更一般的形式為:預處命令更一般的形式為:#IF 表達式1 程序段1#ELIF 表達式2 程序段2 #ELIF 表達式N 程序段N#ELSE 程序段N+1#ENDIF前面的條件編譯命令形式前面的條件編譯命令形式1和形式和形式2也有類似的形式。也有類似的形式。本本 章章 小小 結結1函數(shù)是利用函數(shù)是利用C語言進行結構化程序設計的最基本的概念,語言進行結構化程序設計的最基本的概念,C程序是由函數(shù)組成的??梢园岩粋€復雜的程序分成多個模程序是由函

47、數(shù)組成的。可以把一個復雜的程序分成多個模塊進行設計,而每個模塊是一個函數(shù)。塊進行設計,而每個模塊是一個函數(shù)。MAIN()是是C程序中最程序中最重要的函數(shù),程序運行從函數(shù)重要的函數(shù),程序運行從函數(shù)MAIN()開始,也在函數(shù)開始,也在函數(shù)MAIN()結束。在函數(shù)結束。在函數(shù)MAIN()的執(zhí)行過程中,可以調用其他的執(zhí)行過程中,可以調用其他函數(shù)。函數(shù)。2函數(shù)定義的一般形式為:函數(shù)定義的一般形式為:類型符 函數(shù)名(形式參數(shù)說明) 聲明與定義部分 語句部分類型符指明函數(shù)返回值的類型。如果函數(shù)定義時不指類型符指明函數(shù)返回值的類型。如果函數(shù)定義時不指明類型,系統(tǒng)隱含指定為明類型,系統(tǒng)隱含指定為INT型。形式參

48、數(shù)又稱形參、型。形式參數(shù)又稱形參、虛參或啞元,有兩個作用:其一表示將從主調函數(shù)中虛參或啞元,有兩個作用:其一表示將從主調函數(shù)中接收哪些類型的信息,其二在函數(shù)體中形式參數(shù)可以接收哪些類型的信息,其二在函數(shù)體中形式參數(shù)可以被引用。被引用。3函數(shù)返回值由函數(shù)返回值由RETURN語句實現(xiàn),語句實現(xiàn),RETURN語句的語句的格式為:格式為:RETURN 表達式;函數(shù)先將表達式的值轉換為所定義的類型,然后返回函數(shù)先將表達式的值轉換為所定義的類型,然后返回到主調函數(shù)中的調用表達式。到主調函數(shù)中的調用表達式。4函數(shù)調用是通過函數(shù)調用表達式進行,即:函數(shù)調用是通過函數(shù)調用表達式進行,即:函數(shù)名(實際參數(shù)表)當函

49、數(shù)被調用時,計算機才為形參分配存儲空間。在函數(shù)調當函數(shù)被調用時,計算機才為形參分配存儲空間。在函數(shù)調用時,函數(shù)之間的參數(shù)傳遞也稱為虛實結合。形參從相應的用時,函數(shù)之間的參數(shù)傳遞也稱為虛實結合。形參從相應的實參得到值,稱為傳值調用方式。實參與形參在個數(shù)、類型實參得到值,稱為傳值調用方式。實參與形參在個數(shù)、類型上要匹配。當調用結束,流程返回主調函數(shù)時,形參所占空上要匹配。當調用結束,流程返回主調函數(shù)時,形參所占空間被釋放。間被釋放。5函數(shù)調用前應該已經(jīng)定義或聲明,函數(shù)聲明的一般格式函數(shù)調用前應該已經(jīng)定義或聲明,函數(shù)聲明的一般格式為:為:類型符 函數(shù)名(形參類型1 形參1, 形參類型2 形參2,);

50、或:或:類型符 函數(shù)名(形參類型1,形參類型2,);函數(shù)聲明與函數(shù)定義中的第一行(稱函數(shù)頭)內容一致(也函數(shù)聲明與函數(shù)定義中的第一行(稱函數(shù)頭)內容一致(也稱函數(shù)原型)。函數(shù)定義以函數(shù)體結尾,而函數(shù)聲明不包含稱函數(shù)原型)。函數(shù)定義以函數(shù)體結尾,而函數(shù)聲明不包含函數(shù)體。函數(shù)定義要求分配內存單元,用來存放編譯后的函函數(shù)體。函數(shù)定義要求分配內存單元,用來存放編譯后的函數(shù)指令,而函數(shù)聲明的作用只是通知編譯系統(tǒng)函數(shù)的參數(shù)個數(shù)指令,而函數(shù)聲明的作用只是通知編譯系統(tǒng)函數(shù)的參數(shù)個數(shù)和類型以及函數(shù)返回值的類型。數(shù)和類型以及函數(shù)返回值的類型。6函數(shù)的形參及函數(shù)內定義的變量稱為局部變量,其作用函數(shù)的形參及函數(shù)內定義

51、的變量稱為局部變量,其作用范圍在定義它的函數(shù)或復合語句內。范圍在定義它的函數(shù)或復合語句內。在函數(shù)外部定義的變量稱為全局變量,其作用域是從定義或在函數(shù)外部定義的變量稱為全局變量,其作用域是從定義或聲明處到整個程序結束。聲明處到整個程序結束。7變量的存儲類別指的是變量在計算機中的存放位置,變變量的存儲類別指的是變量在計算機中的存放位置,變量的存儲類有:自動類(量的存儲類有:自動類(AUTO)、外部類()、外部類(EXTERN)、)、靜態(tài)類(靜態(tài)類(STATIC)、寄存器類()、寄存器類(REGISTER)。它們具有)。它們具有不同的生存期和作用域。不同的生存期和作用域。 8一個函數(shù)被調用的過程中可以調用另一個函數(shù),即函數(shù)一個函數(shù)被調用的過程中可以調用另一個函數(shù),即函數(shù)調用允許嵌套。每一次調用時,形參的值自動壓入運行棧,調用允許嵌套。每一次

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論