版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025-2030全球七葉神安片行業(yè)調(diào)研及趨勢(shì)分析報(bào)告
- 2025-2030全球醫(yī)療器械消毒產(chǎn)品行業(yè)調(diào)研及趨勢(shì)分析報(bào)告
- 2025年全球及中國(guó)缺氧帳篷行業(yè)頭部企業(yè)市場(chǎng)占有率及排名調(diào)研報(bào)告
- 2025年全球及中國(guó)有機(jī)空穴傳輸材料行業(yè)頭部企業(yè)市場(chǎng)占有率及排名調(diào)研報(bào)告
- 2025-2030全球連續(xù)式鋰電池?zé)峤鉅t行業(yè)調(diào)研及趨勢(shì)分析報(bào)告
- 競(jìng)業(yè)限制合同協(xié)議書(shū)
- 家具房屋租賃合同書(shū)
- 2025危險(xiǎn)廢物委托處置合同
- 房地產(chǎn)借款合同
- 提高談判技巧的訓(xùn)練課程
- 國(guó)有資產(chǎn)管理法律責(zé)任與風(fēng)險(xiǎn)防控
- 未婚生子的分手協(xié)議書(shū)
- 變更監(jiān)事章程修正案范例
- 北京小客車(chē)指標(biāo)租賃協(xié)議五篇
- 輸液室運(yùn)用PDCA降低靜脈輸液患者外滲的發(fā)生率品管圈(QCC)活動(dòng)成果
- YY/T 0681.2-2010無(wú)菌醫(yī)療器械包裝試驗(yàn)方法第2部分:軟性屏障材料的密封強(qiáng)度
- GB/T 20472-2006硫鋁酸鹽水泥
- 煙氣管道阻力計(jì)算
- 城鄉(xiāng)環(huán)衛(wèi)一體化保潔服務(wù)迎接重大節(jié)日、活動(dòng)的保障措施
- 醫(yī)院-9S管理共88張課件
- 高考作文復(fù)習(xí):議論文論證方法課件15張
評(píng)論
0/150
提交評(píng)論