《計(jì)算機(jī)基礎(chǔ)與C語(yǔ)言程序設(shè)計(jì)》課件第7章_第1頁(yè)
《計(jì)算機(jī)基礎(chǔ)與C語(yǔ)言程序設(shè)計(jì)》課件第7章_第2頁(yè)
《計(jì)算機(jī)基礎(chǔ)與C語(yǔ)言程序設(shè)計(jì)》課件第7章_第3頁(yè)
《計(jì)算機(jī)基礎(chǔ)與C語(yǔ)言程序設(shè)計(jì)》課件第7章_第4頁(yè)
《計(jì)算機(jī)基礎(chǔ)與C語(yǔ)言程序設(shè)計(jì)》課件第7章_第5頁(yè)
已閱讀5頁(yè),還剩129頁(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)介

第7章函數(shù)7.1函數(shù)概述7.2函數(shù)的定義7.3函數(shù)的參數(shù)和函數(shù)的返回值7.4函數(shù)的調(diào)用與聲明7.5函數(shù)的參數(shù)傳送7.6函數(shù)的嵌套調(diào)用和遞歸調(diào)用7.7內(nèi)部變量和外部變量7.8變量的存儲(chǔ)類(lèi)別7.9內(nèi)部函數(shù)和外部函數(shù)7.10模塊化程序設(shè)計(jì)舉例模塊化程序設(shè)計(jì)是進(jìn)行大型程序設(shè)計(jì)的一種有效方法,其基本思想是把一個(gè)復(fù)雜問(wèn)題按功能或?qū)哟畏殖扇舾赡K,即將一個(gè)大任務(wù)分成若干個(gè)子任務(wù),對(duì)應(yīng)每一個(gè)子任務(wù)編制一個(gè)子程序。由于模塊相互獨(dú)立,在設(shè)計(jì)其中任一模塊時(shí)不會(huì)受到其它模塊的干擾,因而可將原來(lái)較為復(fù)雜的問(wèn)題簡(jiǎn)化為一系列簡(jiǎn)單模塊的設(shè)計(jì)。

在C語(yǔ)言中,子程序的功能是由函數(shù)來(lái)完成的。C語(yǔ)言的源程序是由函數(shù)組成的,且至少要有一個(gè)主函數(shù)main()。一般情況下,一個(gè)C程序可以由一個(gè)主函數(shù)和若干個(gè)其它函數(shù)構(gòu)成。主函數(shù)調(diào)用其它函數(shù),其它函數(shù)之間也可以相互調(diào)用。函數(shù)是C語(yǔ)言源程序的基本模塊,C語(yǔ)言通過(guò)對(duì)函數(shù)模塊的調(diào)用實(shí)現(xiàn)特定的功能。

可以說(shuō)C程序的全部工作都是由各式各樣的函數(shù)完成的,所以也把C語(yǔ)言稱為函數(shù)式語(yǔ)言。由于采用了函數(shù)模塊式的結(jié)構(gòu),C語(yǔ)言易于實(shí)現(xiàn)結(jié)構(gòu)化程序設(shè)計(jì),使程序的層次結(jié)構(gòu)清晰,便于程序的編寫(xiě)、閱讀和調(diào)試。

C語(yǔ)言源程序是由函數(shù)組成的。雖然在前面各章節(jié)的介紹中C源程序都只有一個(gè)主函數(shù)main(),但在實(shí)際應(yīng)用中,程序往往由多個(gè)函數(shù)組成。函數(shù)是C源程序的基本模塊,通過(guò)對(duì)函數(shù)模塊的調(diào)用實(shí)現(xiàn)特定的功能。

C語(yǔ)言不僅提供了極為豐富的庫(kù)函數(shù)(如TurboC、MSC都提供了300多個(gè)庫(kù)函數(shù)),還允許用戶建立自己定義的函數(shù)。用戶可把自己的算法編成一個(gè)個(gè)相對(duì)獨(dú)立的函數(shù)模塊,然后用調(diào)用的方法來(lái)使用函數(shù)。7.1函數(shù)概述

1.從函數(shù)定義的角度分類(lèi)

從函數(shù)定義的角度分類(lèi),函數(shù)可分為庫(kù)函數(shù)和用戶自定義函數(shù)兩種。

1)庫(kù)函數(shù)

庫(kù)函數(shù)是由C系統(tǒng)提供的,用戶無(wú)須定義,也不必在程序中做類(lèi)型說(shuō)明,只需在程序前包含有該函數(shù)原型聲明的頭文件便可在程序中直接調(diào)用。在前面各章的例題中反復(fù)用到的printf()、scanf()、getchar()、putchar()、gets()、puts()等函數(shù)均屬此類(lèi)。

2)用戶自定義函數(shù)

用戶自定義函數(shù)指由用戶自己按需要編寫(xiě)的函數(shù)。對(duì)于用戶自定義函數(shù),不僅要在程序中定義函數(shù)本身,而且需要時(shí)在主調(diào)函數(shù)模塊中還必須對(duì)該被調(diào)函數(shù)進(jìn)行類(lèi)型說(shuō)明,然后才能使用。

2.從函數(shù)是否有返回值的角度分類(lèi)

C語(yǔ)言的函數(shù)兼有其它語(yǔ)言中的函數(shù)和過(guò)程兩種功能,從函數(shù)是否有返回值的角度分類(lèi),可分為有返回值函數(shù)和無(wú)返回值函數(shù)兩種。

1)有返回值函數(shù)

此類(lèi)函數(shù)被調(diào)用執(zhí)行完后將向調(diào)用者返回一個(gè)執(zhí)行結(jié)果,稱為函數(shù)返回值。如數(shù)學(xué)函數(shù)即屬于此類(lèi)函數(shù)。由用戶定義的這種要返回函數(shù)值的函數(shù),必須在函數(shù)定義和函數(shù)聲明中明確返回值的類(lèi)型。

2)無(wú)返回值函數(shù)

此類(lèi)函數(shù)用于完成某項(xiàng)特定的處理任務(wù),執(zhí)行完成后不向調(diào)用者返回函數(shù)值。這類(lèi)函數(shù)類(lèi)似于其它語(yǔ)言的過(guò)程。由于函數(shù)無(wú)須返回值,用戶在定義此類(lèi)函數(shù)時(shí)可指定它的返回值為“空類(lèi)型”,空類(lèi)型的說(shuō)明符為“void”。

3.從函數(shù)調(diào)用是否有參數(shù)的角度分類(lèi)

從函數(shù)調(diào)用是否有參數(shù)的角度分類(lèi),可分為無(wú)參函數(shù)和有參函數(shù)兩種。

1)無(wú)參函數(shù)

無(wú)參函數(shù)在函數(shù)定義、函數(shù)聲明及函數(shù)調(diào)用中均不帶參數(shù)。主調(diào)函數(shù)和被調(diào)函數(shù)之間不進(jìn)行參數(shù)傳送。此類(lèi)函數(shù)通常用來(lái)完成一組指定的功能,可以返回或不返回函數(shù)值。

2)有參函數(shù)

有參函數(shù)也稱為帶參函數(shù)。在函數(shù)定義及函數(shù)聲明時(shí)都有參數(shù),稱為形式參數(shù)(簡(jiǎn)稱為形參)。在函數(shù)調(diào)用時(shí)也必須給出參數(shù),稱為實(shí)際參數(shù)(簡(jiǎn)稱為實(shí)參)。進(jìn)行函數(shù)調(diào)用時(shí),主調(diào)函數(shù)把實(shí)參的值傳送給形參,供被調(diào)函數(shù)使用。

4.從函數(shù)的功能角度分類(lèi)

C語(yǔ)言提供了極為豐富的庫(kù)函數(shù),從函數(shù)的功能角度分類(lèi),可分為字符類(lèi)型分類(lèi)函數(shù)、轉(zhuǎn)換函數(shù)、目錄路徑函數(shù)、診斷函數(shù)、圖形函數(shù)、輸入/輸出函數(shù)、接口函數(shù)、字符串函數(shù)、內(nèi)存管理函數(shù)、數(shù)學(xué)函數(shù)、日期和時(shí)間函數(shù)、進(jìn)程控制函數(shù)、其它函數(shù)等。

(1)字符類(lèi)型分類(lèi)函數(shù):用于對(duì)字符按ASCII碼分類(lèi),可分為字母、數(shù)字、控制字符、分隔符、大小寫(xiě)字母等。

(2)轉(zhuǎn)換函數(shù):用于字符或字符串的轉(zhuǎn)換。在字符量和各類(lèi)數(shù)字量(整型、實(shí)型等)之間進(jìn)行轉(zhuǎn)換,在大、小寫(xiě)之間進(jìn)行轉(zhuǎn)換。

(3)目錄路徑函數(shù):用于文件目錄和路徑操作。

(4)診斷函數(shù):用于內(nèi)部錯(cuò)誤檢測(cè)。

(5)圖形函數(shù):用于屏幕管理和各種圖形功能。

(6)輸入/輸出函數(shù):用于完成輸入/輸出功能。

(7)接口函數(shù):用于與DOS、BIOS和硬件的接口。

(8)字符串函數(shù):用于字符串操作和處理。

(9)內(nèi)存管理函數(shù):用于內(nèi)存管理。

(10)數(shù)學(xué)函數(shù):用于數(shù)學(xué)計(jì)算。

(11)日期和時(shí)間函數(shù):用于日期、時(shí)間轉(zhuǎn)換操作。

(12)進(jìn)程控制函數(shù):用于進(jìn)程管理和控制。

(13)其它函數(shù):用于其它各種功能。以上各類(lèi)函數(shù)不僅數(shù)量多,而且有的還需要掌握硬件知識(shí)才能使用,因此要想全部掌握勢(shì)必需要一個(gè)較長(zhǎng)的學(xué)習(xí)過(guò)程。初學(xué)者應(yīng)首先掌握一些最基本、最常用的函數(shù),再逐步深入。有關(guān)庫(kù)函數(shù)的內(nèi)容可查閱相關(guān)資料。

7.2.1函數(shù)的定義形式

在C語(yǔ)言中,函數(shù)定義就是編寫(xiě)完成函數(shù)功能的程序塊。一個(gè)用戶自定義函數(shù)由兩部分組成:函數(shù)首部和函數(shù)體。根據(jù)函數(shù)有無(wú)參數(shù),其定義形式分為以下兩種。

1.無(wú)參函數(shù)的定義形式

類(lèi)型標(biāo)識(shí)符函數(shù)名() /*函數(shù)首部*/

{7.2函?數(shù)?的?定?義說(shuō)明部分

執(zhí)行部分

}/*函數(shù)體*/

2.有參函數(shù)的定義形式

類(lèi)型標(biāo)識(shí)符函數(shù)名(形式參數(shù)表)/*函數(shù)首部*/

{

說(shuō)明部分

執(zhí)行部分

}/*函數(shù)體*/說(shuō)明:

(1)類(lèi)型標(biāo)識(shí)符和函數(shù)名構(gòu)成函數(shù)首部,函數(shù)類(lèi)型標(biāo)識(shí)符指明了函數(shù)的類(lèi)型,也就是函數(shù)返回值的數(shù)據(jù)類(lèi)型;函數(shù)名是由用戶定義的標(biāo)識(shí)符,命名要符合標(biāo)識(shí)符的命名規(guī)則,同一程序中的函數(shù)不能重名,函數(shù)名用來(lái)唯一標(biāo)識(shí)一個(gè)函數(shù)。

(2)花括號(hào){}中的內(nèi)容為函數(shù)體,說(shuō)明部分對(duì)函數(shù)體內(nèi)部所用到的各種變量的類(lèi)型進(jìn)行定義和聲明,對(duì)被調(diào)用的函數(shù)進(jìn)行聲明,執(zhí)行部分是實(shí)現(xiàn)函數(shù)功能的語(yǔ)句序列。

(3)當(dāng)函數(shù)體為空時(shí),稱此函數(shù)為空函數(shù)。調(diào)用空函數(shù)時(shí),空函數(shù)什么也不做。

(4)在C語(yǔ)言中,函數(shù)之間是并列關(guān)系,因此函數(shù)定義中不能包含另一個(gè)函數(shù)的定義,即函數(shù)定義不能嵌套。7.2.2函數(shù)參數(shù)的說(shuō)明

函數(shù)參數(shù)的說(shuō)明有兩種方式:一種是現(xiàn)代方式,一種是傳統(tǒng)方式。現(xiàn)代方式在現(xiàn)在的C語(yǔ)言版本中使用,傳統(tǒng)方式在老的C語(yǔ)言版本中使用,不過(guò)現(xiàn)在的C語(yǔ)言版本也支持傳統(tǒng)方式。

1.現(xiàn)代方式

函數(shù)參數(shù)說(shuō)明的現(xiàn)代方式是將函數(shù)參數(shù)及其類(lèi)型的說(shuō)明都放在函數(shù)首部的形式參數(shù)表中,例如:

intmax(intx,inty)

2.傳統(tǒng)方式

函數(shù)參數(shù)說(shuō)明的傳統(tǒng)方式是將函數(shù)參數(shù)放在函數(shù)首部的形式參數(shù)表中,而其類(lèi)型的說(shuō)明另起一行來(lái)說(shuō)明,例如:

intmax(x,y)

intx,y;7.2.3函數(shù)定義舉例

【例7.1】

編寫(xiě)函數(shù),在屏幕上顯示“Hello,World!”。

voidhello()

{

printf("Hello,World!\n");

}

【例7.2】

編寫(xiě)函數(shù),求兩個(gè)整數(shù)的最大值。

intmax(intx,inty)/*定義函數(shù)類(lèi)型、函數(shù)名、形參*/

{

intm;

if(x>y)/*求兩個(gè)數(shù)的最大值并賦給變量m*/

m=x;

else

m=y;

return(m);/*返回結(jié)果*/

}

【例7.3】

編寫(xiě)函數(shù),求xn。

doublepower(doublex,intn)

{

doublep;

if(n>0)

for(p=1.0;n>0;n--)

p=p*x;

else

p=1.0;

return(p);

}

以上這些函數(shù)只有被主調(diào)函數(shù)調(diào)用后才能實(shí)現(xiàn)其功能。

7.3.1函數(shù)的形式參數(shù)和實(shí)際參數(shù)

函數(shù)定義時(shí)的參數(shù)稱為形式參數(shù),簡(jiǎn)稱為形參。形參在函數(shù)未被調(diào)用時(shí)是沒(méi)有確定的值的,只是形式上的參數(shù)。函數(shù)被調(diào)用時(shí)的參數(shù)稱為實(shí)際參數(shù),簡(jiǎn)稱實(shí)參。實(shí)參可以是常量、變量或表達(dá)式,有確定的值。函數(shù)定義的形參可接受實(shí)參傳來(lái)的值。7.3函數(shù)的參數(shù)和函數(shù)的返回值在函數(shù)定義時(shí),如果函數(shù)有參數(shù),必須定義形參的類(lèi)型。在函數(shù)調(diào)用時(shí),函數(shù)的實(shí)參與形參要求在個(gè)數(shù)上相等,對(duì)應(yīng)的形參和實(shí)參類(lèi)型相同或賦值兼容。

形參和實(shí)參可以同名,也可以不同名。形參是該被調(diào)函數(shù)內(nèi)部的變量,實(shí)參是由主調(diào)函數(shù)提供的,如果實(shí)參是變量,即使形參變量和實(shí)參變量同名,也是兩個(gè)不同的量,占用不同的內(nèi)存單元。

【例7.4】

編寫(xiě)函數(shù) ,然后調(diào)用它來(lái)求 。

#include<stdio.h>

ints(intn)/*n是形參*/

{

inti,sum=0;

for(i=1;i<=n;i++)

sum=sum+i;

return(sum);

}

voidmain()

{

intn,sum;

printf("inputn:");

scanf("%d",&n);

sum=s(n);/*n是實(shí)參*/

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

}程序運(yùn)行結(jié)果:

Inputn:100↙

sum(1..100)=5050

該程序由兩個(gè)函數(shù)main()和s()組成,main()函數(shù)調(diào)用s()函數(shù)。s()函數(shù)有一個(gè)整型形參n。

當(dāng)main()函數(shù)調(diào)用s()函數(shù)時(shí),s()函數(shù)將實(shí)參n的值傳送給形參n,計(jì)算出 。雖然形參和實(shí)參同名,但它們是不同的量,初學(xué)者可以先使用不同名的形參和實(shí)參。7.3.2函數(shù)的返回值

模塊化程序設(shè)計(jì)思想中的子程序一般分為兩種,一種是帶返回值的,稱為函數(shù);另一種是不帶返回值的,稱為過(guò)程。在C語(yǔ)言中并不區(qū)分子程序是函數(shù)還是過(guò)程,而是統(tǒng)稱為函數(shù),但將函數(shù)分為帶返回值的函數(shù)和不帶返回值的函數(shù)兩種。

如果一個(gè)函數(shù)帶返回值,此類(lèi)函數(shù)的功能主要是完成某種計(jì)算,得到計(jì)算結(jié)果,因此它必須使用顯式的返回語(yǔ)句向調(diào)用者返回計(jì)算結(jié)果,這個(gè)計(jì)算結(jié)果就稱為函數(shù)的返回值。用戶定義此類(lèi)函數(shù)時(shí),必須在函數(shù)定義中明確指定函數(shù)返回值的數(shù)據(jù)類(lèi)型,函數(shù)的返回值通過(guò)return語(yǔ)句返回。例7.2中的函數(shù)max(),第一行intmax(intx,inty)中開(kāi)始的int為該函數(shù)返回值的數(shù)據(jù)類(lèi)型,最后的return(m);語(yǔ)句用于向調(diào)用者返回函數(shù)的計(jì)算結(jié)果。

如果一個(gè)函數(shù)無(wú)返回值,此類(lèi)函數(shù)用于完成某項(xiàng)特定的處理任務(wù),函數(shù)的任務(wù)完成后不需要向調(diào)用者返回任何結(jié)果。用戶在定義此類(lèi)函數(shù)時(shí)應(yīng)指定它的返回值為空類(lèi)型,空類(lèi)型的類(lèi)型說(shuō)明符為void,也無(wú)需return語(yǔ)句返回任何結(jié)果。

例7.1中的函數(shù)hello(),第一行voidhello()中開(kāi)始的void表明該函數(shù)的返回值為空類(lèi)型,即無(wú)返回值,最后也無(wú)需return語(yǔ)句向調(diào)用者返回任何結(jié)果。說(shuō)明:

(1)函數(shù)的返回值是通過(guò)被調(diào)用函數(shù)中的return語(yǔ)句實(shí)現(xiàn)的,其使用格式為

return(表達(dá)式);

return表達(dá)式;

return語(yǔ)句的執(zhí)行過(guò)程是首先計(jì)算表達(dá)式的值,然后將計(jì)算結(jié)果返回給調(diào)用者。

(2)帶返回值的函數(shù)只能返回一個(gè)值。

(3)函數(shù)返回值的類(lèi)型由定義函數(shù)時(shí)的函數(shù)首部的函數(shù)類(lèi)型決定。如果函數(shù)值類(lèi)型與return語(yǔ)句中表達(dá)式值的類(lèi)型不一致,則以函數(shù)定義時(shí)函數(shù)首部的類(lèi)型為準(zhǔn)。

(4)

return語(yǔ)句的另一項(xiàng)功能是結(jié)束被調(diào)用的函數(shù),返回到主調(diào)函數(shù)中繼續(xù)執(zhí)行被調(diào)用函數(shù)后面的語(yǔ)句。其使用格式為

return;

(5)在函數(shù)定義時(shí),函數(shù)中允許使用多個(gè)return語(yǔ)句,但只要一個(gè)起作用后,其它的就失去作用了。

C語(yǔ)言程序從主函數(shù)main()開(kāi)始執(zhí)行,一直到主函數(shù)main()的函數(shù)體結(jié)束為止。而函數(shù)的執(zhí)行是通過(guò)對(duì)函數(shù)的調(diào)用來(lái)執(zhí)行的,調(diào)用者稱為主調(diào)函數(shù),被調(diào)用者稱為被調(diào)函數(shù)。當(dāng)被調(diào)函數(shù)被調(diào)用結(jié)束時(shí),從被調(diào)函數(shù)結(jié)束的位置再返回到主調(diào)函數(shù)中被調(diào)函數(shù)后面的語(yǔ)句繼續(xù)執(zhí)行,直到主函數(shù)main()結(jié)束。7.4函數(shù)的調(diào)用與聲明7.4.1函數(shù)調(diào)用的形式

有參函數(shù)調(diào)用的形式如下:

函數(shù)名(實(shí)參表列)

無(wú)參函數(shù)調(diào)用的形式如下:

函數(shù)名(

)

對(duì)于有參函數(shù),如果實(shí)參表列包含多個(gè)實(shí)參,則各實(shí)參間用逗號(hào)隔開(kāi),實(shí)參與形參的個(gè)數(shù)相等,對(duì)應(yīng)的類(lèi)型應(yīng)相同或賦值兼容。7.4.2函數(shù)調(diào)用的方式

可以用兩種方式調(diào)用函數(shù)。

1.函數(shù)語(yǔ)句

C語(yǔ)言中的函數(shù)可以僅進(jìn)行某些操作而不返回值,這時(shí)函數(shù)的調(diào)用可作為一條獨(dú)立的語(yǔ)句,如:

函數(shù)名(實(shí)參表列);

函數(shù)名(

);

注意:函數(shù)后面有一個(gè)分號(hào)“;”。

2.函數(shù)表達(dá)式

當(dāng)所調(diào)用的函數(shù)有返回值且需要使用返回值時(shí),函數(shù)的調(diào)用可作為表達(dá)式出現(xiàn)在允許表達(dá)式出現(xiàn)的任何地方。例如,例7.3中的power()函數(shù)在調(diào)用時(shí)就可作為函數(shù)表達(dá)式(y=power(x,n);)。

實(shí)際上,對(duì)于有返回值的函數(shù),如果主調(diào)函數(shù)不使用其返回值,也可以以函數(shù)語(yǔ)句的調(diào)用方式來(lái)調(diào)用。例如,程序中可以使用

getch();

主調(diào)函數(shù)并不關(guān)心其返回值(即鍵入的字符)是什么,它只需要用戶敲一個(gè)鍵即可。7.4.3函數(shù)的聲明

調(diào)用一個(gè)函數(shù),首先要求該函數(shù)已經(jīng)被定義,但有時(shí)僅有定義仍然不能正確調(diào)用該函數(shù),這時(shí)需要增加對(duì)被調(diào)用函數(shù)的聲明。

函數(shù)聲明的目的是使編譯系統(tǒng)在編譯階段對(duì)函數(shù)的調(diào)用進(jìn)行合法性檢查,判斷形參與實(shí)參的類(lèi)型及個(gè)數(shù)是否匹配。

函數(shù)聲明采用函數(shù)原型的方法。函數(shù)原型就是已定義函數(shù)的首部。

對(duì)于有參函數(shù),函數(shù)聲明的形式如下:

類(lèi)型標(biāo)識(shí)符函數(shù)名(形參表列);

對(duì)于無(wú)參函數(shù),函數(shù)聲明的形式如下:

類(lèi)型標(biāo)識(shí)符函數(shù)名();

注意:函數(shù)聲明除了函數(shù)的首部,最后還有一個(gè)分號(hào)“;”。函數(shù)聲明可以放在開(kāi)始,即所有函數(shù)的前面,也可以放在主調(diào)函數(shù)內(nèi)調(diào)用被調(diào)函數(shù)前。事實(shí)上,在下面3種情形下可以省略對(duì)被調(diào)函數(shù)的聲明:

(1)被調(diào)函數(shù)的定義出現(xiàn)在主調(diào)函數(shù)之前。

(2)被調(diào)函數(shù)的返回值類(lèi)型是整型或字符型。整型是系統(tǒng)默認(rèn)的類(lèi)型。

(3)被調(diào)函數(shù)是C語(yǔ)言提供的庫(kù)函數(shù)。雖然庫(kù)函數(shù)的調(diào)用不需要作函數(shù)聲明,但必須把該庫(kù)函數(shù)的頭文件用

#include命令包含在源程序的最前面。例如,像getchar()、putchar()這樣的函數(shù)定義是放在stdio.h頭文件中的,只要在程序最前面加上#include<stdio.h>就可以了。

【例7.5】

編寫(xiě)函數(shù)xn,然后調(diào)用它來(lái)求213。

#include<stdio.h>

voidmain()

{

doublepower(doublex,intn);/*對(duì)函數(shù)power()進(jìn)行聲明*/

doublex=2.0,y;

intn=13;

y=power(x,n);/*調(diào)用函數(shù)power()*/

printf("y=%lf",y);

}

doublepower(doublex,intn)/*對(duì)函數(shù)power()進(jìn)行定義*/

{

doublep;

if(n>0)

for(p=1.0;n>0;n--)

p=p*x;

else

p=1.0;

return(p);

}程序運(yùn)行結(jié)果:

y=8192.000000

模塊化程序設(shè)計(jì)中,參數(shù)傳送是既重要又復(fù)雜的概念,如果不能掌握函數(shù)的參數(shù)傳送,就無(wú)法編寫(xiě)出正確的函數(shù)。本節(jié)將進(jìn)一步介紹函數(shù)的形參和實(shí)參的特點(diǎn)以及兩者之間的關(guān)系。7.5函數(shù)的參數(shù)傳送7.5.1實(shí)參與形參之間的數(shù)據(jù)傳送

形參出現(xiàn)在函數(shù)定義中,在整個(gè)函數(shù)體內(nèi)都可以使用,離開(kāi)該函數(shù)則不能使用。實(shí)參出現(xiàn)在主調(diào)函數(shù)中,進(jìn)入被調(diào)函數(shù)后,實(shí)參變量也不能使用。形參和實(shí)參的功能是作數(shù)據(jù)傳送。發(fā)生函數(shù)調(diào)用時(shí),主調(diào)函數(shù)把實(shí)參的值傳送給被調(diào)函數(shù)的形參從而實(shí)現(xiàn)主調(diào)函數(shù)向被調(diào)函數(shù)的數(shù)據(jù)傳送。函數(shù)的實(shí)參和形參進(jìn)行數(shù)據(jù)傳送時(shí)具有以下特點(diǎn):

(1)函數(shù)調(diào)用中發(fā)生的數(shù)據(jù)傳送是單向的,即只能把實(shí)參的值傳送給形參,而不能把形參的值反向傳送給實(shí)參,這稱為按值傳送,也稱傳值調(diào)用。因此在函數(shù)調(diào)用過(guò)程中,形參的值發(fā)生改變,而實(shí)參中的值不會(huì)變化。

(2)形參變量只有在被調(diào)用時(shí)才分配內(nèi)存單元,在調(diào)用結(jié)束時(shí),即刻釋放所分配的內(nèi)存單元。因此,形參只有在函數(shù)內(nèi)部有效。函數(shù)調(diào)用結(jié)束返回主調(diào)函數(shù)后則不能再使用該形參變量。

(3)實(shí)參可以是常量、變量、表達(dá)式、函數(shù)等,無(wú)論實(shí)參是何種類(lèi)型的量,在進(jìn)行函數(shù)調(diào)用時(shí),它們都必須具有確定的值,以便把這些值傳送給形參,因此應(yīng)預(yù)先用賦值、輸入等方法使實(shí)參獲得確定值。

(4)實(shí)參和形參在數(shù)量上、類(lèi)型上、順序上應(yīng)嚴(yán)格一致,否則會(huì)發(fā)生“類(lèi)型不匹配”的錯(cuò)誤。

【例7.6】實(shí)參與形參之間的數(shù)據(jù)單向傳送。

#include<stdio.h>

voidp(intx,inty)

{

x=x+3;

y=y+7;

printf("x=%d,y=%d\n",x,y);

}

voidmain()

{

inta=8,b=10;

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

p(a,b);

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

}

程序運(yùn)行結(jié)果:

a=8,b=10

x=11,y=17

a=8,b=10

本程序中定義了一個(gè)函數(shù)p(),該函數(shù)的功能僅是對(duì)傳送進(jìn)來(lái)的參數(shù)做了一個(gè)簡(jiǎn)單的運(yùn)算,即對(duì)第一個(gè)參數(shù)x加3,對(duì)第二個(gè)參數(shù)y加7。在主函數(shù)中說(shuō)明定義了兩個(gè)變量a和b,分別初始化為8和10。當(dāng)主函數(shù)調(diào)用函數(shù)p()時(shí),系統(tǒng)給形參開(kāi)辟兩個(gè)存儲(chǔ)單元x和y,將實(shí)參a和b的值傳送給函數(shù)p()的形參x和y。傳送過(guò)程如圖7-1所示。

圖7-1實(shí)參與形參之間的數(shù)據(jù)單向傳送在主函數(shù)中第一次用printf()輸出a和b的值,分別為8和10。調(diào)用函數(shù)p(),將實(shí)參a和b的值分別傳送給形參x和y后,函數(shù)p()內(nèi)部對(duì)形參x和y進(jìn)行了改變,用printf()輸出x和y的值,分別為11和17。當(dāng)調(diào)用函數(shù)p()結(jié)束返回主函數(shù)后,再用printf()輸出a和b的值,仍然分別為8和10??梢?jiàn)函數(shù)內(nèi)部對(duì)形參的改變并沒(méi)有改變實(shí)參的值,即實(shí)參的值不隨形參的變化而變化。7.5.2數(shù)組作參數(shù)

數(shù)組也可以作為函數(shù)參數(shù)使用。數(shù)組作為函數(shù)的參數(shù)有兩種形式:一種是數(shù)組元素作實(shí)參使用;另一種是數(shù)組名作為函數(shù)的形參和實(shí)參使用。

1.數(shù)組元素作函數(shù)實(shí)參

數(shù)組元素就是下標(biāo)變量,它與普通變量并無(wú)區(qū)別,因此它作為函數(shù)實(shí)參使用時(shí)與普通變量是完全相同的,在進(jìn)行函數(shù)調(diào)用時(shí),把作為實(shí)參的數(shù)組元素的值傳送給形參,實(shí)現(xiàn)單向的值傳送。

【例7.7】

編寫(xiě)程序,判別一個(gè)整數(shù)數(shù)組中各元素的值,若大于0則輸出該值,否則輸出0。

#include<stdio.h>

voidprint(intn)

{

if(n>0)

printf("%5d",n);

else

printf("%5d",0);

}

voidmain()

{

inti,a[10];

for(i=0;i<10;i++)

scanf("%d",&a[i]);

for(i=0;i<10;i++)

print(a[i]);

}

程序運(yùn)行結(jié)果:

2354-1390-64891234095-1↙

235409008912340950

2.數(shù)組名作函數(shù)實(shí)參

數(shù)組名實(shí)際上表示的是整個(gè)數(shù)組的首地址。如果調(diào)用函數(shù)的實(shí)參是數(shù)組名,則被調(diào)用函數(shù)的形參也應(yīng)該是數(shù)組類(lèi)型。尤為重要的是,如果實(shí)參是數(shù)組名,形參是數(shù)組類(lèi)型,則調(diào)用函數(shù)和被調(diào)用函數(shù)存取的將是相同的一組空間,原因是實(shí)參傳送給形參的是一組空間的首地址。

【例7.8】

編寫(xiě)程序,輸入10個(gè)學(xué)生的成績(jī),對(duì)這些成績(jī)進(jìn)行排序,輸出排序前后的結(jié)果。

#include<stdio.h>

voidsort(floata[],intn) /*排序函數(shù)*/

{

inti,j,k;

floatt;

for(i=0;i<n-1;i++){

k=i;

for(j=i+1;j<n;j++)

if(a[k]<a[j])

k=j;

t=a[i];

a[i]=a[k];

a[k]=t;

}

}

voidprint(floata[],intn) /*輸出函數(shù)*/

{

inti;

for(i=0;i<n;i++)

printf("%5.1f",a[i]);

printf("\n");

}

voidmain() /*主函數(shù)*/

{

inti;

floata[10];

for(i=0;i<10;i++)

scanf("%f",&a[i]);

printf("Beforesort:\n");

print(a,10);

sort(a,10);

printf("Aftersort:\n");

print(a,10);

}

程序運(yùn)行結(jié)果:

65897856958869748623↙

Beforesort:

65.089.078.056.095.088.069.074.086.023.0

Aftersort:

95.089.088.086.078.074.069.065.056.023.0

用數(shù)組名做函數(shù)的實(shí)參,應(yīng)分別在主調(diào)函數(shù)和被調(diào)函數(shù)中定義數(shù)組,實(shí)參數(shù)組與形參數(shù)組要一一對(duì)應(yīng),而且應(yīng)該是同一類(lèi)型。實(shí)參數(shù)組與形參數(shù)組大小可以一致也可以不一致,因?yàn)镃編譯系統(tǒng)對(duì)形參數(shù)組大小不作檢查,只是將實(shí)參數(shù)組的首地址傳送給形參數(shù)組。實(shí)際上,形參數(shù)組可以不指定大小,在定義形參數(shù)組時(shí)后面跟一個(gè)空的方括號(hào)即可。

多維數(shù)組名也可以作為函數(shù)的實(shí)參,在定義形參數(shù)組時(shí)可以指定每一維的長(zhǎng)度,但可以不指定第一維的長(zhǎng)度。

【例7.9】

編寫(xiě)程序,將一個(gè)3行4列的矩陣的每一列的最小值存入另一個(gè)一維數(shù)

組中。

#include<stdio.h>

voidmin(inta[][4],intb[])

{

inti,j,k;

for(j=0;j<4;j++){

k=a[0][j];

for(i=1;i<3;i++)

if(k>a[i][j])

k=a[i][j];

b[j]=k;

}

}

voidprint_a2(inta[][4],intm)

{

inti,j;

for(i=0;i<m;i++){

for(j=0;j<4;j++)

printf("%6d",a[i][j]);

printf("\n");

}

}

voidprint_a1(inta[],intm)

{

inti;

for(i=0;i<m;i++)

printf("%6d",a[i]);

printf("\n");

}

voidmain()

{

inta[3][4]={73,87,13,68,90,23,65,45,46,76,93,80},b[4];

printf("Arrayis:\n");

print_a2(a,3);

min(a,b);

printf("Minis:\n");

print_a1(b,4);

}程序運(yùn)行結(jié)果:

Arrayis:

73871368

90236545

46769380

Minis:

46231345

7.6.1函數(shù)的嵌套調(diào)用

在C語(yǔ)言中,雖然函數(shù)之間的關(guān)系是并列的,在函數(shù)定義時(shí)不能嵌套定義,但是允許函數(shù)嵌套調(diào)用,例如函數(shù)A調(diào)用函數(shù)B,函數(shù)B又調(diào)用函數(shù)C。

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

【例7.10】

函數(shù)的嵌套調(diào)用。

#include<stdio.h>

voidprint();/*函數(shù)聲明*/

voidprnline();/*函數(shù)聲明*/

voidmain()

{

inti,j;

putchar('\n');

for(i=0;i<2;i++){

for(j=0;j<3;j++)

print();/*函數(shù)調(diào)用*/

putchar('\n');

}

}

voidprint()/*函數(shù)定義*/

{

putchar('*');

prnline();/*函數(shù)調(diào)用*/

}

voidprnline()/*函數(shù)定義*/

{

putchar('_');

}

程序運(yùn)行結(jié)果:

*_*_*_

*_*_*_

以上程序中的函數(shù)調(diào)用關(guān)系為:main()函數(shù)在執(zhí)行過(guò)程中調(diào)用print()函數(shù),print()函數(shù)在執(zhí)行過(guò)程中又調(diào)用prnline()函數(shù),形成了函數(shù)之間的嵌套調(diào)用。7.6.2函數(shù)的遞歸調(diào)用

函數(shù)的遞歸調(diào)用是指在函數(shù)調(diào)用的過(guò)程中,函數(shù)直接或間接地調(diào)用了函數(shù)自身。含有直接或間接調(diào)用自身的函數(shù)稱為遞歸函數(shù)。C語(yǔ)言允許函數(shù)的遞歸調(diào)用。在遞歸調(diào)用中,主調(diào)函數(shù)又是被調(diào)函數(shù)。執(zhí)行遞歸函數(shù)將反復(fù)調(diào)用其自身,每調(diào)用一次就進(jìn)入新的一層。

一般來(lái)說(shuō),遞歸需要有邊界條件、遞歸前進(jìn)段和遞歸返回段。當(dāng)邊界條件不滿足時(shí),遞歸前進(jìn);當(dāng)邊界條件滿足時(shí),遞歸返回。一個(gè)問(wèn)題要采用遞歸方法來(lái)解決時(shí),必須符合以下三個(gè)條件:

(1)要解決的問(wèn)題可以轉(zhuǎn)化為一個(gè)新的問(wèn)題,而這個(gè)新的問(wèn)題的解法仍與原來(lái)的解法相同,只是所處理的對(duì)象有規(guī)律地遞減。

(2)可以應(yīng)用這個(gè)轉(zhuǎn)化過(guò)程使問(wèn)題得到解決。

(3)必定要有一個(gè)結(jié)束遞歸的條件。

【例7.11】

用遞歸方法求。

問(wèn)題分析:

求可以用以下數(shù)學(xué)關(guān)系表示:

從以上表達(dá)式可以看到,當(dāng)n>0時(shí),求n!

的問(wèn)題可以轉(zhuǎn)化為求n(n-1)!

的新問(wèn)題,而求(n-1)!

的解法與原來(lái)求n!

的解法相同,只是運(yùn)算對(duì)象由n變成了n-1,因此求

(n-1)!

的問(wèn)題又可以轉(zhuǎn)化為求

(n-1)(n-2)!

的新問(wèn)題,……,每次轉(zhuǎn)化為新問(wèn)題時(shí),運(yùn)算對(duì)象就遞減1,直到運(yùn)算對(duì)象的值減至0時(shí),階乘的值為1,遞歸不再進(jìn)行下去,這就是求n!

這個(gè)遞歸算法的結(jié)束條件。程序如下:

#include<stdio.h>

intfac(intn)

{

intt;

if(n==0)

return(1);

else{

t=n*fac(n-1);

return(t);

}

}

voidmain()

{

intn,y;

printf("Inputn:");

scanf("%d",&n);

if(n<0)

printf("Dataerror!\n");

else{

y=fac(n);

printf("%d!=%d\n",n,y);

}

}

程序運(yùn)行結(jié)果:

Inputn:5↙

5!=120

【例7.12】

用遞歸方法求Fibonacci數(shù)列。

Fibonacci數(shù)列的遞推公式如下:

程序如下:

#include<stdio.h>

longfibonacci(intn)

{

longt;

if(n==1||n==2)

t=1;

else

t=fibonacci(n-1)+fibonacci(n-2);

return(t);

}

voidmain()

{

intn;

longy;

printf("Inputn:");

scanf("%d",&n);

y=fibonacci(n);

printf("Fibonacci(%d)=%ld\n",n,y);

}程序運(yùn)行結(jié)果:

Inputn:10↙

Fibonacci(10)=55

【例7.13】

Hanoi塔問(wèn)題。

這是一個(gè)古典的數(shù)學(xué)問(wèn)題。問(wèn)題是這樣的:

古代有一個(gè)梵塔,塔內(nèi)有A、B、C3個(gè)座,開(kāi)始時(shí)A座上有64個(gè)盤(pán)子,盤(pán)子大小不等,大的在下,小的在上。有一個(gè)老和尚想把這64個(gè)盤(pán)子從A座移到C座,要求是每次只允許移動(dòng)一個(gè)盤(pán)子,可以借助B座,且在移動(dòng)的過(guò)程中都要保證三個(gè)座上的盤(pán)子大的在下,小的在上。編寫(xiě)程序顯示移動(dòng)的步驟。問(wèn)題分析:

將n階問(wèn)題轉(zhuǎn)化成n-1階問(wèn)題:

第一步,把A座上的n-1個(gè)盤(pán)子借助C座移到B座上;

第二步,把A座上剩下的一個(gè)盤(pán)子移到C座上;

第三步,把B座上的n-1個(gè)盤(pán)子借助A座移到C座。

其中,第一步和第三步的方法是相同的。

遞歸出口:n=1,此時(shí)A座上只有一個(gè)盤(pán)子,直接將其移到C座上即可。程序如下:

#include<stdio.h>

voidmove(charx,chary)

{

printf("%c-->%c\n",x,y);

}

voidhanoi(intn,chara,charb,charc)

{

if(n==1)

move(a,c);

else{

hanoi(n-1,a,c,b);

move(a,c);

hanoi(n-1,b,a,c);

}

}

voidmain()

{

intn;

printf("Inputn:");

scanf("%d",&n);

hanoi(n,'A','B','C');

}

程序運(yùn)行結(jié)果:

Inputn:3↙

A-->C

A-->B

C-->B

A-->C

B-->A

B-->C

A-->C

遞歸作為一種算法在程序設(shè)計(jì)語(yǔ)言中廣泛應(yīng)用,它通常把一個(gè)大型復(fù)雜的問(wèn)題層層轉(zhuǎn)化為一個(gè)與原問(wèn)題相似的規(guī)模較小的問(wèn)題來(lái)求解,遞歸策略只需少量的程序就可描述出解題過(guò)程所需要的多次重復(fù)計(jì)算,大大地減少了程序的代碼量。遞歸的能力在于用有限的語(yǔ)句來(lái)定義對(duì)象的無(wú)限集合。用遞歸思想寫(xiě)出的程序往往十分簡(jiǎn)潔易懂。遞歸的缺點(diǎn):

遞歸算法解題的運(yùn)行效率較低。在遞歸調(diào)用的過(guò)程中,系統(tǒng)為每一層的返回點(diǎn)、局部量等開(kāi)辟了棧來(lái)存儲(chǔ)。遞歸次數(shù)過(guò)多容易造成棧溢出等。

變量是程序運(yùn)行過(guò)程中值可以改變的量。編譯系統(tǒng)為變量分配內(nèi)存單元,用來(lái)存放程序運(yùn)行過(guò)程中的輸入數(shù)據(jù)、中間結(jié)果和最終結(jié)果等。

變量的一個(gè)特性是變量的數(shù)據(jù)類(lèi)型,它用來(lái)說(shuō)明該變量在內(nèi)存中所占的字節(jié)數(shù),以及變量的運(yùn)算規(guī)則。變量的另一個(gè)特性就是屬性,變量的屬性包含兩個(gè)方面,即變量的作用域和變量的存儲(chǔ)類(lèi)別。7.7內(nèi)部變量和外部變量變量的作用域是指變量的合法使用范圍。變量的作用域與定義變量的位置密切相關(guān),變量只能在它的作用域內(nèi)使用。

變量的存儲(chǔ)類(lèi)別是指變量在內(nèi)存中的存儲(chǔ)位置。變量的存儲(chǔ)類(lèi)別決定著變量的生存期,變量的生存期是指變量在內(nèi)存或寄存器中存在的時(shí)間段。

變量從作用域來(lái)區(qū)分可分為內(nèi)部變量和外部變量。7.7.1內(nèi)部變量

在函數(shù)內(nèi)部或復(fù)合語(yǔ)句內(nèi)部定義的變量稱為內(nèi)部變量。

內(nèi)部變量的作用域是指從定義該變量的位置開(kāi)始到它所在函數(shù)或復(fù)合語(yǔ)句結(jié)束。在它的作用域外,內(nèi)部變量是不可見(jiàn)的。換言之,函數(shù)或復(fù)合語(yǔ)句內(nèi)定義的內(nèi)部變量是不能被其它的函數(shù)或復(fù)合語(yǔ)句所引用的。

內(nèi)部變量的生存期是指定義該變量到函數(shù)結(jié)束或復(fù)合語(yǔ)句結(jié)束這段時(shí)間。

內(nèi)部變量包含自動(dòng)類(lèi)型內(nèi)部變量、寄存器類(lèi)型內(nèi)部變量和靜態(tài)類(lèi)型內(nèi)部變量。另外,函數(shù)的形參也屬于內(nèi)部變量,因?yàn)楹瘮?shù)形參的作用域只在該函數(shù)內(nèi)。使用內(nèi)部變量有助于實(shí)現(xiàn)信息隱藏,即使不同的函數(shù)定義了同名的內(nèi)部變量,也不會(huì)相互影響。

例如:

intf1(inta)

{

intb,c;

...

}

intf2(floatx,floaty)

{

floatz;

...

}

voidmain()

{

charc1,c2;

...

}

在函數(shù)f1()內(nèi)定義了三個(gè)內(nèi)部變量a、b、c,其中a為形參,在函數(shù)f1()的范圍內(nèi)a、b、c有效,也即a、b、c的作用域僅限于函數(shù)f1()內(nèi)。同理,x、y、z的作用域僅限于函數(shù)f2()內(nèi),c1、c2的作用域僅限于主函數(shù)main()內(nèi)。說(shuō)明:

(1)主函數(shù)中定義的內(nèi)部變量也只能在主函數(shù)中使用,不能在其它函數(shù)中使用。同時(shí),主函數(shù)中也不能使用其它函數(shù)中定義的內(nèi)部變量,因?yàn)橹骱瘮?shù)也是一個(gè)函數(shù)。它和其它函數(shù)是平等關(guān)系。

(2)形參變量屬于被調(diào)函數(shù)的內(nèi)部變量,實(shí)參變量屬于主調(diào)函數(shù)的內(nèi)部變量。允許在不同的函數(shù)中使用相同的內(nèi)部變量名,它們代表不同的對(duì)象,分配不同的存儲(chǔ)單元,互不干擾,也不會(huì)發(fā)生混淆。7.7.2外部變量

在函數(shù)外任意位置定義的變量稱為外部變量。

外部變量的作用域是指從定義它的位置開(kāi)始,直至它所在的源程序文件結(jié)束。對(duì)于不在作用范圍的程序段,可以通過(guò)在段內(nèi)對(duì)外部變量進(jìn)行聲明的方式來(lái)拓展外部變量的作用域。外部變量包含非靜態(tài)類(lèi)型外部變量和靜態(tài)類(lèi)型外部變量。例如:

在同一個(gè)源程序文件中,如果外部變量與內(nèi)部變量同名,則在內(nèi)部變量的作用域內(nèi),外部變量將被屏蔽,即不起作用。

外部變量的使用增加了函數(shù)之間傳送數(shù)據(jù)的途徑。在外部變量的作用域內(nèi),任何函數(shù)都可以引用該外部變量。一個(gè)函數(shù)對(duì)外部變量的修改,能影響到其它引用該外部變量的函數(shù),因此,外部變量使用不當(dāng),會(huì)產(chǎn)生意外的錯(cuò)誤。外部變量的使用也會(huì)使得函數(shù)的通用性降低,從結(jié)構(gòu)化程序設(shè)計(jì)的角度看,函數(shù)應(yīng)視為完成單一功能的程序段,過(guò)多使用外部變量,會(huì)使函數(shù)之間的依賴性增加,增加函數(shù)的耦合性。一般情況下,除非性能的特別要求,建議盡量避免使用外部變量。

【例7.14】外部變量與內(nèi)部變量同名。

#include<stdio.h>

inta=3,b=5;/*a、b是外部變量*/

intf()

{

printf("f:a=%d,b=%d\n",a,b);/*輸出外部變量a、b的值*/

}

voidmain()

{

inta=12,b=25;/*a、b是內(nèi)部變量*/

printf("main:a=%d,b=%d\n",a,b);/*輸出內(nèi)部變量a、b的值*/

f();

}

程序運(yùn)行結(jié)果:

main:a=12,b=25

f:a=3,b=5

7.8.1變量的存儲(chǔ)類(lèi)別概述

C程序運(yùn)行時(shí)占用的內(nèi)存空間分為三部分,如圖7-2所示。程序運(yùn)行期間的數(shù)據(jù)分別存放在靜態(tài)存儲(chǔ)區(qū)和動(dòng)態(tài)存儲(chǔ)區(qū)。靜態(tài)存儲(chǔ)區(qū)用來(lái)存放程序運(yùn)行期間所需占用固定存儲(chǔ)單元的變量,如外部變量和靜態(tài)類(lèi)型的內(nèi)部變量。動(dòng)態(tài)存儲(chǔ)區(qū)用來(lái)存放不需要長(zhǎng)期占用內(nèi)存單元的變量,如函數(shù)的形參和函數(shù)調(diào)用時(shí)的返回值等。7.8變量的存儲(chǔ)類(lèi)別

圖7-2C程序運(yùn)行時(shí)占用的內(nèi)存空間變量的存儲(chǔ)類(lèi)別分為兩類(lèi):動(dòng)態(tài)存儲(chǔ)類(lèi)別和靜態(tài)存儲(chǔ)類(lèi)別。

對(duì)于動(dòng)態(tài)存儲(chǔ)類(lèi)別的變量,當(dāng)程序運(yùn)行進(jìn)入定義它的函數(shù)或復(fù)合語(yǔ)句時(shí)才被分配存儲(chǔ)空間,當(dāng)程序運(yùn)行結(jié)束離開(kāi)此函數(shù)或復(fù)合語(yǔ)句時(shí),所占用的內(nèi)存空間被釋放。動(dòng)態(tài)存儲(chǔ)類(lèi)別是一種節(jié)省內(nèi)存空間的存儲(chǔ)方式,它是在需要時(shí)分配內(nèi)存空間,不需要時(shí)釋放內(nèi)存空間的變量。動(dòng)態(tài)存儲(chǔ)類(lèi)別的變量又分為兩種:自動(dòng)類(lèi)型變量和寄存器類(lèi)型變量。自動(dòng)類(lèi)型變量被存放于內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū),用auto說(shuō)明符來(lái)定義;寄存器類(lèi)型變量被存放于寄存器中,用register說(shuō)明符來(lái)定義。對(duì)于靜態(tài)存儲(chǔ)類(lèi)別的變量,在程序運(yùn)行整個(gè)過(guò)程中,始終占用固定的內(nèi)存空間,直至程序運(yùn)行結(jié)束,才釋放占用的內(nèi)存空間。靜態(tài)存儲(chǔ)類(lèi)別的變量被存放于內(nèi)存空間的靜態(tài)存儲(chǔ)區(qū),可用static和extern來(lái)定義和聲明變量。

變量的存儲(chǔ)類(lèi)別決定著變量的生存期。變量的作用域和生存期是兩個(gè)不同的概念。作用域指的是可見(jiàn)性,生存期指的是存在性??梢?jiàn)是指變量在它的作用域內(nèi)有效,可對(duì)其進(jìn)行存取、引用等;不可見(jiàn)是指變量在它的作用域外無(wú)效,不能對(duì)其實(shí)施有效操作。存在是指變量占用內(nèi)存;不存在是指變量所占用內(nèi)存已經(jīng)被釋放。7.8.2內(nèi)部變量的存儲(chǔ)類(lèi)別

內(nèi)部變量的作用域是指定義該變量的函數(shù)或復(fù)合語(yǔ)句的范圍。內(nèi)部變量的存儲(chǔ)類(lèi)別是指它在內(nèi)存中的存儲(chǔ)方式。內(nèi)部變量可存放于內(nèi)存的動(dòng)態(tài)區(qū)、內(nèi)存的靜態(tài)區(qū)或寄存器。但無(wú)論內(nèi)部變量存放于何處,其作用域都是不變的。

1.自動(dòng)存儲(chǔ)類(lèi)型內(nèi)部變量

自動(dòng)存儲(chǔ)類(lèi)型內(nèi)部變量的存儲(chǔ)單元被分配在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)。自動(dòng)存儲(chǔ)類(lèi)型變量的定義形式為

auto類(lèi)型變量名

在函數(shù)內(nèi)部,自動(dòng)存儲(chǔ)類(lèi)型變量是系統(tǒng)默認(rèn)的變量類(lèi)型,關(guān)鍵字“auto”可以省略,因此,以下兩種定義變量的方式是等價(jià)的:

inta;

autointa;

函數(shù)內(nèi)部不做特別說(shuō)明定義的變量、函數(shù)的形參都是自動(dòng)存儲(chǔ)類(lèi)型內(nèi)部變量,它們都是在進(jìn)入函數(shù)或復(fù)合語(yǔ)句時(shí)被分配內(nèi)存單元的,在該函數(shù)或復(fù)合語(yǔ)句運(yùn)行期間一直存在,在函數(shù)或復(fù)合語(yǔ)句運(yùn)行結(jié)束時(shí)自動(dòng)釋放這些內(nèi)存單元。自動(dòng)存儲(chǔ)類(lèi)型內(nèi)部變量的作用域和生存期是一致的,在它的生存期內(nèi)都是有效的、可見(jiàn)的。函數(shù)內(nèi)部的自動(dòng)存儲(chǔ)類(lèi)型內(nèi)部變量在每次函數(shù)調(diào)用時(shí),系統(tǒng)都會(huì)在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)為它們重新分配內(nèi)存單元,隨著函數(shù)的頻繁調(diào)用,某個(gè)變量的存儲(chǔ)位置隨著程序的運(yùn)行是不斷變化的,所以未賦初值的自動(dòng)存儲(chǔ)類(lèi)型內(nèi)部變量的值是不確定的。

2.寄存器存儲(chǔ)類(lèi)型內(nèi)部變量

寄存器存儲(chǔ)類(lèi)型內(nèi)部變量的存儲(chǔ)單元被分配在寄存器中。其定義形式為

register類(lèi)型變量名;

如:

registerintj;

寄存器存儲(chǔ)類(lèi)型內(nèi)部變量的作用域、生存期與自動(dòng)存類(lèi)型內(nèi)部變量相同。因?yàn)榧拇嫫鞯拇嫒∷俣缺葍?nèi)存快得多,通常將頻繁使用變量放在寄存器中(如循環(huán)體中涉及的內(nèi)部變量),以提高程序的執(zhí)行速度。

計(jì)算機(jī)中寄存器的個(gè)數(shù)是有限的,寄存器的數(shù)據(jù)位數(shù)也是有限的,所以定義寄存器存儲(chǔ)類(lèi)型內(nèi)部變量的個(gè)數(shù)不能太多,并且只有整型變量和字符型變量可以定義為寄存器存儲(chǔ)類(lèi)型內(nèi)部變量。

寄存器存儲(chǔ)類(lèi)型內(nèi)部變量的定義通常是不必要的,現(xiàn)在優(yōu)化的編譯系統(tǒng)能夠識(shí)別頻繁使用的變量,并能夠在不需要編程人員作出寄存器存儲(chǔ)類(lèi)型定義的情況下,就把這些變量存放在寄存器中。

3.靜態(tài)存儲(chǔ)類(lèi)型內(nèi)部變量

靜態(tài)存儲(chǔ)類(lèi)型內(nèi)部變量的存儲(chǔ)單元被分配在內(nèi)存空間的靜態(tài)存儲(chǔ)區(qū)中。靜態(tài)存儲(chǔ)類(lèi)型內(nèi)部變量的定義形式為

static類(lèi)型變量名

靜態(tài)存儲(chǔ)類(lèi)型內(nèi)部變量在編譯的時(shí)候被分配內(nèi)存、賦初值,并且只被賦初值一次,對(duì)未賦初值的靜態(tài)存儲(chǔ)類(lèi)型內(nèi)部變量,系統(tǒng)自動(dòng)給它賦初值0(或

'\0')。在整個(gè)程序運(yùn)行期間,靜態(tài)存儲(chǔ)類(lèi)型內(nèi)部變量在內(nèi)存的靜態(tài)存儲(chǔ)區(qū)占用固定的內(nèi)存單元,即使它所在的函數(shù)調(diào)用結(jié)束,也不釋放存儲(chǔ)單元,其值也會(huì)繼續(xù)保留,下次再調(diào)用該函數(shù)時(shí),靜態(tài)存儲(chǔ)類(lèi)型變量繼續(xù)使用原來(lái)的存儲(chǔ)單元,仍使用原來(lái)存儲(chǔ)單元中的值。可以利用靜態(tài)存儲(chǔ)類(lèi)型變量的這個(gè)特點(diǎn),編寫(xiě)需要在被調(diào)用結(jié)束后仍保存內(nèi)部變量值的函數(shù)。

靜態(tài)存儲(chǔ)類(lèi)型變量的作用域仍然是定義該變量的函數(shù)或復(fù)合語(yǔ)句內(nèi)部。雖然靜態(tài)存儲(chǔ)類(lèi)型變量在整個(gè)程序運(yùn)行期間都是存在的,但在它的作用域外,它是不可見(jiàn)的,即不能被其它函數(shù)引用。

【例7.15】

靜態(tài)存儲(chǔ)類(lèi)型變量舉例。

#include<stdio.h>

intsum(intx)

{

staticints=0;/*定義靜態(tài)存儲(chǔ)類(lèi)型內(nèi)部變量*/

s=s+x;

return(s);

}

main()

{

inti,k;

for(i=1;i<=10;i++)

k=sum(i);

printf("\n0+1+...+%2d=%2d\n",i-1,k);

}

程序運(yùn)行結(jié)果:

1+...+10=55

說(shuō)明:程序從main()函數(shù)開(kāi)始運(yùn)行,此時(shí),函數(shù)sum()內(nèi)的靜態(tài)存儲(chǔ)類(lèi)型內(nèi)部變量s在靜態(tài)存儲(chǔ)區(qū)已被分配存儲(chǔ)單元并初始化為0。main()函數(shù)調(diào)用函數(shù)sum()10次,第一次為“k=sum(1);”,s是靜態(tài)存儲(chǔ)類(lèi)型內(nèi)部變量,初始化為0,執(zhí)行“s=s+x;”,s內(nèi)保存的值是1(0+1);第二次為“k=sum(2);”,s不再初始化,執(zhí)行“s=s+x;”,s內(nèi)保存的是3(1+2);第三次為“k=sum(3);”,執(zhí)行“s=s+x;”,s內(nèi)保存的是6(3+3);……;第十次為“k=sum(10);”,執(zhí)行“s=s+x;”,s內(nèi)保存的是55(45+10)。7.8.3外部變量的存儲(chǔ)類(lèi)別

外部變量只能存放在內(nèi)存的靜態(tài)存儲(chǔ)區(qū)。外部變量的生存期是整個(gè)程序的運(yùn)行期。外部變量的作用域局限于定義它的程序文件,經(jīng)過(guò)聲明后,則可被程序的其它程序文件中的函數(shù)所引用。

外部變量分為外部存儲(chǔ)類(lèi)型外部變量和靜態(tài)存儲(chǔ)類(lèi)型外部變量。

1.外部存儲(chǔ)類(lèi)型外部變量

外部存儲(chǔ)類(lèi)型外部變量是在所有函數(shù)外定義的外部變量,其定義形式為

類(lèi)型變量名

外部存儲(chǔ)類(lèi)型外部變量的作用域是整個(gè)程序,只需加上聲明,就可以被所在程序的其它程序文件所引用。

外部存儲(chǔ)類(lèi)型外部變量也稱為程序級(jí)外部變量。

2.靜態(tài)存儲(chǔ)類(lèi)型外部變量

靜態(tài)存儲(chǔ)類(lèi)型外部變量也是在所有函數(shù)外定義的外部變量,其定義形式為

static類(lèi)型變量名

靜態(tài)存儲(chǔ)類(lèi)型外部變量的作用域是其所在的程序文件。雖然它在程序運(yùn)行期間一直存在,但它不能被其它程序文件引用。靜態(tài)外部變量能夠限制它的作用域的擴(kuò)展,達(dá)到信息隱蔽的目的。

靜態(tài)存儲(chǔ)類(lèi)型外部變量也稱為文件級(jí)外部變量。

3.外部變量的聲明

外部變量的定義是在所有函數(shù)的外部,它的使用卻是在函數(shù)的內(nèi)部。如果外部變量不在程序文件的開(kāi)頭定義,則其作用域只限于從定義處到程序文件的結(jié)束。如果在定義處之前或其它程序文件中引用(外部存儲(chǔ)類(lèi)型外部變量),則應(yīng)該在引用之前對(duì)其進(jìn)行聲明,表示該變量是一個(gè)已經(jīng)定義的外部變量。外部變量一經(jīng)聲明,就可以從聲明處起,合法地引用該外部變量。外部變量的聲明形式為

extern類(lèi)型變量名;

在外部變量的作用域內(nèi)(即從定義處到程序文件結(jié)束)可以省略對(duì)外部變量的聲明。

【例7.16】

外部變量聲明舉例。

/*file1.c*/

intx=0;

main()

{

}

/*file2.c*/

externintx;/*外部變量聲明*/

intfunc()

{

}

說(shuō)明:該程序由兩個(gè)程序文件file1.c和file2.c組成。在file1.c中定義了外部整型變量x,在file2.c中對(duì)file1.c中定義的外部整型變量x進(jìn)行了聲明,這樣file2.c中的函數(shù)就可以引用file1.c中定義的外部整型變量x了。

溫馨提示

  • 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)論