C語言程序設(shè)計課件 第6章_第1頁
C語言程序設(shè)計課件 第6章_第2頁
C語言程序設(shè)計課件 第6章_第3頁
C語言程序設(shè)計課件 第6章_第4頁
C語言程序設(shè)計課件 第6章_第5頁
已閱讀5頁,還剩76頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第6章函數(shù)6.1函數(shù)定義和聲明6.2函數(shù)調(diào)用過程6.3函數(shù)的遞歸與嵌套調(diào)用6.4作用域與存儲類型6.5函數(shù)與數(shù)組6.6函數(shù)的綜合示例本章小結(jié)

6.1函數(shù)定義和聲明

6.1.1函數(shù)定義的一般形式

函數(shù)定義的一般形式為函數(shù)類型說明函數(shù)名(形參說明表){說明部分;執(zhí)行部分;}

6.1.2函數(shù)定義的要點

1.函數(shù)類型的說明

如上所述,函數(shù)類型指函數(shù)返回值的數(shù)據(jù)類型。函數(shù)返回時可能得到0個數(shù)據(jù)、1個數(shù)據(jù)或多個數(shù)據(jù)。

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

如果函數(shù)沒有返回值,則一般在定義函數(shù)時把函數(shù)類型寫為void。例如:

voidPRINT()

{

printf("Test\n");

}

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

如果函數(shù)有1個返回值,則在被調(diào)用函數(shù)的函數(shù)體中有return語句。此時函數(shù)類型的定義應(yīng)根據(jù)return語句后的表達式的數(shù)據(jù)類型來定義。例如:

intmax(inta,intb)

{

returna>b?a:b;

}

3)函數(shù)有多個返回值

如果函數(shù)有多個返回值,則在被調(diào)函數(shù)的函數(shù)體中一般無return語句。多個值的返回是通過全局變量、數(shù)組或指針來實現(xiàn)的,這將在后面的章節(jié)中進行介紹。

2.函數(shù)的命名

函數(shù)名是函數(shù)的標識,函數(shù)的命名規(guī)則與變量命名規(guī)則相同。通過引用函數(shù)名,可調(diào)用該函數(shù)。

3.形參表及形參的說明

1)形式參數(shù)

在函數(shù)定義中寫在圓括號中的參數(shù)稱為形式參數(shù)(簡稱形參)。不帶形參的函數(shù)其形參表有兩種表現(xiàn)形式:一是形參表空著,二是在形參表中寫上“void”以確定沒有形參。例如:

voidPRINT(void)

{

printf("Thisisaexample\n");

}

兩種表現(xiàn)形式的區(qū)別:若形參表空著,則在函數(shù)調(diào)用時,給一個或多個實在參數(shù)(簡稱實參),編譯器不會提示有錯誤或警告;若形參表中寫“void”,在函數(shù)調(diào)用時,給一個或多個實參,則編譯器會給出警告“warningC4087:'PRINT':declaredwith'void'parameterlist”。

有形參函數(shù)的形參表由一個或多個形參組成,各參數(shù)間用逗號分隔,且必須給出每個參數(shù)的數(shù)據(jù)類型。

2)函數(shù)間利用參數(shù)傳遞數(shù)據(jù)

函數(shù)間通過參數(shù)傳遞數(shù)據(jù),是指將調(diào)用函數(shù)中的實參向被調(diào)用函數(shù)中的形參按從右向左順序依次傳遞。

實參向形參傳遞數(shù)據(jù)是指實參將值單向傳遞給形參,形參值的變化不傳遞給實參。其原因在于每次調(diào)用函數(shù),都必須給形參分配新的空間,而不是復(fù)用原來實參空間,

因此修改形參不會影響實參。

例如:

即實參a、b兩個變量的值沒有得到交換。這里用圖6-1來表示swap()函數(shù)調(diào)用開始時和結(jié)束后各參數(shù)的值。

圖6-1swap函數(shù)調(diào)用過程中各參數(shù)的變化

5.主函數(shù)的定義

本書采用VisualC++2010Express作為集成開發(fā)環(huán)境。對于main()函數(shù)的定義特進行如下說明:

(1)同樣的main()函數(shù)定義和源碼,源文件的擴展名為“.c”時的編譯結(jié)果與擴展名為“.cpp”時的編譯結(jié)果可能不同,建議擴展名用“.c”,以確定采用C語言(而不是C++語言)的語法規(guī)則編譯程序。

(2)對于C語言主函數(shù)的定義,在C99中規(guī)定了如下兩種標準格式。

①?intmain(void)

②?intmain(intargc,char*argv[])

(3)?VisualC++2010Express主要是用于C++程序開發(fā)的,對于C語言,兼容C89標準,因此,本書有些C程序中的main()函數(shù)仍然定義成main(){……}這種簡單的形式。

(4)雖然VisualC++2010Express允許voidmain()的定義,但也要少用。因為這種用法不符合C99標準,很多編譯器不支持。

(5)?main()函數(shù)的返回值用于說明程序的退出狀態(tài)。

綜上所述,我們可以得出如下結(jié)論:

(1)如果C程序單純只考慮能在VisualC++2010Express中編譯通過,則主函數(shù)的定義形式幾乎不受限制,可以定義成main(){……}這種簡單的形式,也可以定義成voidmain(){……}。

(2)如果C程序要考慮可移植性,則要遵循主流標準。調(diào)試C/C++程序,符合C99標準及C++98標準的主函數(shù)定義形式為

6.1.3函數(shù)的聲明

定義好的函數(shù)需要調(diào)用時,一般應(yīng)在主調(diào)函數(shù)中對被調(diào)函數(shù)進行聲明,即向編譯系統(tǒng)聲明將要調(diào)用此函數(shù),并將有關(guān)信息(如被調(diào)用函數(shù)名、函數(shù)類型、形參的個數(shù)及類型等)通知編譯系統(tǒng)。

函數(shù)聲明的格式如下:

函數(shù)類型說明函數(shù)名(形參及其類型);

函數(shù)聲明又稱為函數(shù)接口(Interface)或接口說明,這種格式很像函數(shù)的定義,初學(xué)者很容易混淆。其實,它們的區(qū)別是很明顯的:函數(shù)定義具有函數(shù)體,且在源程序中只能定義一次;函數(shù)聲明沒有函數(shù)體,且在不同的主調(diào)函數(shù)中可多次出現(xiàn)。

函數(shù)從來源上分,有系統(tǒng)庫函數(shù)和用戶自定義函數(shù)兩種。

對于庫函數(shù)的接口說明,系統(tǒng)按功能不同組成相應(yīng)的頭文件,如所有數(shù)學(xué)函數(shù)接口說明頭文件為“math.h”,標準輸入/輸出庫函數(shù)接口說明頭文件為“stdio.h”。如果調(diào)用系統(tǒng)庫函數(shù),必須用預(yù)編譯命令“#include”把相應(yīng)的頭文件包含在源程序的首部,之后就不必再進行接口說明了。例如,在某函數(shù)中調(diào)用數(shù)學(xué)函數(shù)sqrt(),則在源程序的開頭加命令:

#include<math.h>

對于用戶自定義函數(shù),若被調(diào)函數(shù)定義在主調(diào)函數(shù)之前,可缺省函數(shù)接口聲明;若被調(diào)函數(shù)定義在主調(diào)函數(shù)之后,則一定要進行函數(shù)接口聲明。

6.2函數(shù)調(diào)用過程6.2.1函數(shù)調(diào)用的一般形式一個C程序是由一個或多個獨立的函數(shù)組成的,在一個函數(shù)中引用另一個函數(shù),稱為函數(shù)的調(diào)用。其中引用另一個函數(shù)的函數(shù),稱為主調(diào)函數(shù),被引用的函數(shù),稱為被調(diào)用函數(shù)。主調(diào)函數(shù)中的參數(shù),稱為實在參數(shù),而被調(diào)用函數(shù)中的參數(shù)稱為形式參數(shù)。一般地,主函數(shù)main()只能被操作系統(tǒng)調(diào)用,不能被其他函數(shù)調(diào)用;主函數(shù)main()可以調(diào)用庫函數(shù)或其他函數(shù);除主函數(shù)main()外,其他函數(shù)之間可以互相調(diào)用。

在一個程序中,通過函數(shù)調(diào)用將各函數(shù)聯(lián)系在一起,程序總是從main()函數(shù)開始執(zhí)行并調(diào)用所需要的函數(shù),完成所調(diào)用函數(shù)的功能后,返回到main()函數(shù)繼續(xù)執(zhí)行,最后當main()函數(shù)執(zhí)行完畢,整個程序運行結(jié)束。假設(shè)有main()函數(shù)和fun()函數(shù),它們的調(diào)用過程如圖6-2所示。圖6-2函數(shù)調(diào)用執(zhí)行過程示意圖

一般函數(shù)的調(diào)用執(zhí)行過程歸納如下:

(1)為被調(diào)用函數(shù)的所有形式參數(shù)分配內(nèi)存,并將實在參數(shù)的值,按從右向左的方式一一對應(yīng)地賦給相應(yīng)的形式參數(shù)(對于無參函數(shù),不做此工作)。

(2)程序控制由主調(diào)函數(shù)進入被調(diào)函數(shù)的函數(shù)體,之后依次執(zhí)行被調(diào)用函數(shù)中變量定義部分,為局部變量分配存儲空間,執(zhí)行函數(shù)體中的可執(zhí)行語句。

(3)當執(zhí)行到“return”語句時,計算返回值(如果是無返回值的函數(shù),不做這項工作),之后釋放本函數(shù)中定義的局部變量和形式參數(shù)所占用的存儲空間(對于static類型變量,其空間不釋放),最后返回主調(diào)函數(shù)繼續(xù)執(zhí)行其他語句。

例6-4從鍵盤輸入兩個整數(shù),求較大的整數(shù)。

程序執(zhí)行的簡單過程如下:①程序從main()函數(shù)開始執(zhí)行,當執(zhí)行到main()函數(shù)體第三行“c=max(a,b);”時,調(diào)用max()函數(shù),把實在參數(shù)b、a的值傳遞給函數(shù)max()的形式參數(shù)y、x,并在主函數(shù)的該處設(shè)置函數(shù)斷點,然后系統(tǒng)轉(zhuǎn)去執(zhí)行函數(shù)max()的函數(shù)體;②max()函數(shù)比較由主函數(shù)傳遞來的兩個整數(shù),然后執(zhí)行return語句返回到主調(diào)函數(shù)的斷點處,并將函數(shù)的返回值也傳送給主調(diào)函數(shù);③main()函數(shù)將max()函數(shù)的返回值賦給主調(diào)函數(shù)的內(nèi)部變量c,程序繼續(xù)往下執(zhí)行,輸出較大數(shù),此時主函數(shù)執(zhí)行完畢,整個程序運行結(jié)束。

6.2.2函數(shù)調(diào)用的參數(shù)傳遞

對帶有參數(shù)的函數(shù)進行調(diào)用時,存在著如何將實參傳遞給形參的問題。根據(jù)實參傳遞給形參值的不同,參數(shù)傳遞通常有值傳遞方式和地址傳遞方式兩種。

1.值傳遞方式

所謂值傳遞方式是指函數(shù)調(diào)用時,為形參分配內(nèi)存單元,并將實參的值復(fù)制到形參中,當調(diào)用結(jié)束后,形參所占內(nèi)存單元被釋放,實參的內(nèi)存單元仍保留并維持原值。

例6-5函數(shù)參數(shù)的值傳遞方式示例。

該程序首先在main()函數(shù)中定義了兩個整型變量x和y,其初始值分別為7和11,然后調(diào)用swap()自定義函數(shù)試圖交換x、y的值,可結(jié)果是,調(diào)用函數(shù)swap()以后,x和y的值并沒有交換,x仍然是7,y仍然是11。為什么會出現(xiàn)這種情況呢?

這是因為實參x和y對應(yīng)的內(nèi)存單元與形參a和b所對應(yīng)的內(nèi)存單元是各不相同的,在函數(shù)調(diào)用時,只是將x的值7傳遞給形參a,y的值11傳遞給形參b,在swap()函數(shù)體內(nèi)只是將a和b的值交換了,即a的值變?yōu)?1,b的值變?yōu)?,當函數(shù)返回時,a和b的內(nèi)存單元就釋放了,x和y所對應(yīng)的內(nèi)存單元并沒有進行任何的改變。這就好像是我復(fù)印一份文件給你,在你的文件上修改都不會改變我的文件一樣。該程序函數(shù)參數(shù)調(diào)用的過程如圖6-3所示。圖6-3函數(shù)參數(shù)值傳遞方式示意圖

2.地址傳遞方式

所謂地址傳遞方式是指,函數(shù)調(diào)用時將實參數(shù)據(jù)的存儲地址作為參數(shù)傳遞給形參。其特點是形參與實參占用同樣的內(nèi)存單元,函數(shù)中對形參值的改變也會改變實參的值。因此函數(shù)參數(shù)的地址傳遞方式可實現(xiàn)調(diào)用函數(shù)與被調(diào)函數(shù)之間的雙向數(shù)據(jù)傳遞。注意,實參和形參必須是地址常量或變量。

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

6.3.1函數(shù)的遞歸調(diào)用C語言中除允許一個函數(shù)調(diào)用其他函數(shù)外,還允許函數(shù)自己調(diào)用自己,這種函數(shù)稱為遞歸函數(shù)。

1.遞歸概念

函數(shù)的遞歸調(diào)用是指一個函數(shù)在它的函數(shù)體內(nèi)直接或間接地調(diào)用它自身。因此,遞歸調(diào)用有兩種方式:直接遞歸和間接遞歸。直接遞歸指的是函數(shù)直接調(diào)用自身的過程,如圖6-4(a)所示;間接遞歸指的是一個函數(shù)通過其他函數(shù)調(diào)用自身的過程,如圖6-4(b)所示,函數(shù)1調(diào)用函數(shù)2,函數(shù)2又調(diào)用函數(shù)1。

圖6-4兩種遞歸調(diào)用示意圖

例如:

fact(intn) /*fact函數(shù)定義*/

{

t=n*fact(n-1);

}

上述函數(shù)fact()中,函數(shù)fact()又要調(diào)用函數(shù)本身,它是直接遞歸。而遞歸函數(shù)怎么定義呢?以fact(n)=n!為例。因為

由①、②兩式可得fact(n)?=?n?×?fact(n?-?1)。假設(shè)想求fact(5)的值,則必須先求得fact(4)的值,同理想求fact(4)的值,則必須求fact(3)……,因而會無限地往下遞歸,程序無法得到終止。在調(diào)用過程中假設(shè)fact(1)=1,將值回代,則可得fact(2)的值,同理可得fact(3)、fact(4)的值,最后將其值回代得到fact(5)的值。因此,函數(shù)遞歸調(diào)用一定要有遞歸終止的條件,即當傳遞過去某個值時,函數(shù)值不再調(diào)用函數(shù)本身,而是一個確定值或過程。這也說明,遞歸函數(shù)的定義應(yīng)包括兩部分:函數(shù)的遞歸關(guān)系和函數(shù)遞歸終止條件。

2.遞歸舉例

例6-6用遞歸法求fact(n)?=?n!。

計算階乘可用如下形式描述:

它的遞歸調(diào)用和值的回代過程(設(shè)n?=?5)如圖6-5所示。主函數(shù)對fact(5)進行0級調(diào)用時,n=5,不滿足n==1的條件,此時必須進行1級調(diào)用,得到fact(4)的值后,才能得出“fact(5)=5*fact(4)”。同樣,計算fact(4)時需進行2級調(diào)用,即調(diào)用fact(3)。計算fact(3)要進行3級調(diào)用,即調(diào)用fact(2)。計算fact(2)需進行4級調(diào)用,即調(diào)用fact(1),此時n=1,滿足條件n==1,得到p=1。返回p=1,即fact(1)返回至上層調(diào)用函數(shù)fact(2)處,得到“p=2*1=2”。

返回p=2,即fact(2)返回至上層調(diào)用函數(shù)fact(3)處,得到“p=3*2=6”。返回p=6,即fact(3)返回至上層調(diào)用函數(shù)fact(4)處,得到“p=4*6=24”。返回p=24,即fact(4)返回至上層調(diào)用函數(shù)fact(5)處,得到“p=5*24=120”。返回p=120,即fact(5)返回至上層調(diào)用函數(shù)main()處,輸出運算結(jié)果。

圖6-5遞歸調(diào)用和值的回代

例6-8漢諾塔問題。

有3個塔,每個都可以堆放若干個盤子。開始時,所有盤子均在塔A上,并且,盤從上到下,按直徑增大的次序放置(如圖6-6所示)。設(shè)計一個移動盤子的程序,使得塔A上的所有盤子借助于塔B移到塔C上。這里有兩個限制條件:一是一次只能搬動一個盤子,二是任何時候不能把大盤子放在比它小的盤子的上面。圖6-6漢諾塔問題示意圖

解題思路要移動這n個盤子,可以定義一個函數(shù):

move(n,a,b,c)

其中,字符型變量a、b、c分別表示A、B、C3個塔,函數(shù)move(n,a,b,c)表示將n個盤子從塔A(借助于塔B)移到塔C上。這個問題可以使用遞歸調(diào)用方法解決,在n?>?0的前提下,函數(shù)move(n,a,b,c)通過下列3步實現(xiàn)移動。

(1)調(diào)用move(n-1,a,c,b),即將n-1個盤子從塔A(借助于塔C)移到塔B上。目的是讓塔A上的第n個盤子(最下面的盤子)上無其他盤子。

(2)將底下的第n個盤子從A塔移到C塔。

(3)調(diào)用move(n-1,b,a,c),即將n?-?1個疊放在塔B上的盤子(借助于塔A)移到C塔。

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

將孤立的函數(shù)堆砌在一起并不能建立關(guān)系,實現(xiàn)程序的功能。程序中的函數(shù)需要通過相互調(diào)用建立關(guān)系。C語言規(guī)定,在一個函數(shù)內(nèi)部不允許再定義函數(shù),即函數(shù)不可嵌套定義,但是允許一個函數(shù)調(diào)用另外一個函數(shù),這個被調(diào)用的函數(shù)還可以調(diào)用其他的函數(shù),以形成任意深度的調(diào)用層次。這就是函數(shù)的嵌套調(diào)用。圖6-7給出了函數(shù)嵌套調(diào)用的示意圖。

圖6-7函數(shù)嵌套調(diào)用的示意圖

例6-9計算s?=?22!?+?32!。

解題思路本題可編寫兩個函數(shù),一個是用來計算平方值的函數(shù)f1,另一個是用來計算階乘值的函數(shù)f2。主函數(shù)先調(diào)f1計算出平方值,再在f1中以平方值為實參,調(diào)用f2計算其階乘值,之后返回f1,最后返回主函數(shù),在循環(huán)程序中計算累加和。

6.4作用域與存儲類型

6.4.1作用域與生存期1.作用域所謂變量的作用域,就是指某個變量在其生存期內(nèi)可被使用的范圍。C語言中有兩種變量:一種變量只能在所定義的模塊內(nèi)部有效,稱為局部變量或內(nèi)部變量;另一種變量從定義點開始至整個源程序結(jié)束都有效,稱為全局變量或外部變量。

1)局部變量

局部變量指在函數(shù)或復(fù)合語句中定義的變量,只在本函數(shù)或復(fù)合語句范圍內(nèi)有效(從定義點開始到函數(shù)或復(fù)合語句結(jié)束),即只有在本函數(shù)或復(fù)合語句內(nèi)才能使用它們,在此函數(shù)或復(fù)合語句以外是不能使用它們。

注意:

(1)主函數(shù)中定義的變量也只在主函數(shù)中有效,而不因為是在主函數(shù)中定義的而在整個文件或程序中有效。主函數(shù)也不能使用其他函數(shù)中定義的變量。

(2)不同函數(shù)中可以使用相同名稱的變量,它們代表不同的對象,互不干擾。例如,在f1函數(shù)中定義了變量b和c,倘若在f2函數(shù)中也定義變量b和c,它們在內(nèi)存中占不同的單元。

(3)形式參數(shù)也是局部變量。在函數(shù)中可以使用本函數(shù)聲明的形參,在函數(shù)外則不能引用。

(4)在一個函數(shù)內(nèi)部,可以在復(fù)合語句中定義變量,這些變量只在本復(fù)合語句中有效。

2)全局變量

局變量指在函數(shù)之外定義的變量。全局變量的有效范圍為從定義點開始到本源程序結(jié)束。在此范圍內(nèi)它可以被本程序中所有函數(shù)所使用。在一個函數(shù)中既可以使用本函數(shù)中的局部變量,又可以使用有效的全局變量。

2.生存期

所謂變量的生存期,就是變量存活的周期。程序中的變量都要占用一定的內(nèi)存空間,但并不是所有的變量在程序開始執(zhí)行時就占用內(nèi)存。為了節(jié)省內(nèi)存,避免變量互相干擾,不可能讓所有的變量始終存在,因此只有在必要時才為變量分配內(nèi)存。當變量占用內(nèi)存時,變量就生成了。當變量不再有用時,程序?qū)⑨尫抛兞克加玫膬?nèi)存,變量就撤銷了。變量從被生成到被撤銷的這段時間稱為變量的生存期。它實際上就是變量占用內(nèi)存的時間。

6.4.2變量的存儲類型

由變量的生存期可知,有的變量在程序運行的整個過程都是存在的,而有的變量則是在調(diào)用其所在的函數(shù)時才臨時分配內(nèi)存單元,而在函數(shù)調(diào)用結(jié)束后就馬上釋放了,變量也不再存在了。因此變量的存儲有兩種情況:一是變量從定義點開始就被分配內(nèi)存單元(即產(chǎn)生),直到程序運行結(jié)束才釋放內(nèi)存,這種方式稱為靜態(tài)存儲方式;二是變量帶有臨時性,隨調(diào)用的模塊(如文件、函數(shù)或復(fù)合語句)分配內(nèi)存單元,模塊調(diào)用結(jié)束,釋放內(nèi)存,這種方式稱為動態(tài)存儲方式。

全局變量采用靜態(tài)存儲方式,程序開始執(zhí)行時給全局變量分配內(nèi)存空間,程序執(zhí)行完畢釋放。在程序執(zhí)行過程中它們占據(jù)固定的存儲單元,而不是動態(tài)地進行內(nèi)存分配和釋放。在函數(shù)中定義的變量,在函數(shù)調(diào)用開始時分配動態(tài)存儲空間,函數(shù)結(jié)束時釋放這些空間。在程序執(zhí)行過程中,這種分配和釋放是動態(tài)的。

C語言中變量的定義有兩個屬性:一是定義變量的數(shù)據(jù)類型;另一個是定義變量的存儲類型。變量的數(shù)據(jù)類型規(guī)定了變量的存儲空間大小和取值范圍,變量的存儲類型規(guī)定了變量的生存期和作用域。因此,定義一個變量的一般形式為

[存儲類型]數(shù)據(jù)類型變量標識符表;

其中[]內(nèi)為可選項。

不同存儲類型的變量在計算機內(nèi)部的存放位置是不同的。不同的存放位置決定了變量的存儲類型,這也就決定了變量的生存期和作用域。變量可以存放在內(nèi)存中的動態(tài)數(shù)據(jù)存儲區(qū)或靜態(tài)數(shù)據(jù)存儲區(qū)中,也可以存儲在CPU的寄存器中。

變量的存儲類型有4種,分別是自動型、寄存器型、外部型和靜態(tài)型,其說明符分別是auto、register、extern和static。下面結(jié)合程序示例,分別說明它們各自的生存期和作用域。

1.自動型(auto)

在各個函數(shù)或復(fù)合語句內(nèi)定義的變量,也稱為自動變量。自動變量用關(guān)鍵字“auto”進行標識,可缺省。

例如,在例6-4中的程序中,主函數(shù)main()的函數(shù)體中定義了3個自動變量a、b、c;在max()函中定義了1個自動變量z(形參也為自動變量)。當程序運行main()函數(shù)時,系統(tǒng)為a、b、c變量分別分配內(nèi)存單元;在調(diào)用max()函數(shù)時,系統(tǒng)為max()函數(shù)的形參x、y和自動變量z分配內(nèi)存單元,即生命開始,調(diào)用結(jié)束釋放x、y、z的空間,即生命結(jié)束,其壽命為函數(shù)調(diào)用開始到結(jié)束期間,稱為局部壽命。x、y、z的使用也只能在max()函數(shù)內(nèi)部,這稱為局部可用。

2.寄存器型(register)

如果有一些變量使用頻繁(例如,在一個函數(shù)中執(zhí)行1000000次循環(huán),每次循環(huán)中都要引用某局部變量),則要為存取該變量的值花不少時間。為提高執(zhí)行效率,C語言允許將局部變量的值放在CPU中的寄存器中,需要用時直接對寄存器讀寫數(shù)據(jù)。存儲類型為寄存器型的變量稱為寄存器變量。由于CPU的通用寄存器數(shù)量有限,在程序中允許定義的寄存器變量一般以少于8個為宜。如果定義為寄存器變量的數(shù)目超過系統(tǒng)所提供的寄存器數(shù)目,編譯系統(tǒng)自動將超出的變量設(shè)為自動型存儲類型。由于在計算機中對寄存器的讀寫速度遠遠高于對內(nèi)存的讀寫速度,因此這樣可以提高執(zhí)行效率。寄存器變量用關(guān)鍵字register聲明。

3.外部型(extern)

定義在所有函數(shù)(包括主函數(shù))外部的變量稱為外部變量。外部變量是一種全局變量。

1)外部變量的特性

對于外部變量,系統(tǒng)在編譯時是將外部變量的內(nèi)存單元分配在數(shù)據(jù)存儲區(qū),在整個程序文件運行結(jié)束后系統(tǒng)才收回其存儲單元。因此外部變量的作用域是從外部變量定義點開始到源程序運行結(jié)束,即外部變量的壽命是全局的。在定義點之后的所有函數(shù),都可以使用外部變量,也就是說其作用域也是全局的。

例6-12求ax2?+?bx?+?c?=?0(a?≠?0)的根。

解題思路在a≠0的情況下。根據(jù)b2?-?4ac的不同值,方程分別有兩個不等的實根、兩個相等的實根和兩個共軛的虛根。如果傳遞方程的3個系數(shù)a、b、c給函數(shù),分別求出方程的根,則上述3種情況都需要返回兩個數(shù)據(jù),由于這里通過return語句無法實現(xiàn),因此可借用外部變量實現(xiàn)。

程序開頭的語句“floatx1,x2;”定義的是兩個外部變量x1、x2,編譯時分配x1、x2的存儲空間,程序運行期間其空間一直存在。在其后定義的f1()函數(shù)、f2()函數(shù)、f3()函數(shù)和main()函數(shù)都可以引用變量x1、x2,也就是說在f1()函數(shù)、f2()函數(shù)、f3()函數(shù)中改寫x1、x2值,就可以在main()函數(shù)中輸出對應(yīng)x1、x2值。這實現(xiàn)了不同函數(shù)之間的數(shù)據(jù)共享或通信。

2)外部變量的引用

外部變量的作用域是定義點開始到源程序的結(jié)束。若在定義點之前或別的源程序中要引用外部變量,則在引用該變量之前,需進行外部變量的引用說明。

外部變量的引用說明的一般形式為

extern外部變量數(shù)據(jù)類型外部變量名表;

一個C程序可以由很多個程序文件組成,每個文件稱為一個編譯單位。外部變量主要用于在多個編譯單位間傳遞數(shù)據(jù)。若兩個編譯單位A和B需要交換信息,可在編譯單位A中定義一個外部變量A,并把信息存放在其中,編譯單位B要引用該變量需把該變量說明為外部型,告訴系統(tǒng)該變量在其他編譯單位中已經(jīng)定義了。

4.靜態(tài)型(static)

靜態(tài)變量是分配在內(nèi)存中的。它們在程序開始運行時就分配了固定的存儲單元,在程序運行過程中不釋放,直到程序運行結(jié)束才釋放它所占的存儲空間。如果用static說明外部變量為靜態(tài)型,則該外部變量只能在本程序中使用。

1)靜態(tài)局部變量

靜態(tài)局部變量是定義在函數(shù)體的復(fù)合語句中,用關(guān)鍵字“static”進行標識的變量。靜態(tài)局部變量定義的一般形式為

static變量數(shù)據(jù)類型變量名表;

對于靜態(tài)局部變量,系統(tǒng)在編譯時將其內(nèi)存單元分配在靜態(tài)數(shù)據(jù)存儲區(qū),直到程序運行結(jié)束,對應(yīng)的內(nèi)存單元才釋放。靜態(tài)局部變量只有在編譯時可以賦初值,以后每次調(diào)用時不再分配內(nèi)存單元和初始化,只是引用上一次函數(shù)調(diào)用結(jié)束時的值。其作用域只限于其所定義的函數(shù)或復(fù)合語句中。因此靜態(tài)局部變量是一種具有全局壽命、局部可用的變量。

2)靜態(tài)全局變量

定義在所有函數(shù)(包括主函數(shù))之外,用關(guān)鍵字“static”標識的變量,稱為靜態(tài)全局變量。靜態(tài)全局變量和外部變量有共同點:都具有全局壽命,即在整個程序運行期間都存在。但二者在使用上有區(qū)別:靜態(tài)全局變量只能在所定義的文件中使用,具有對文件的局部可見性;而一般的外部變量可以在所有文件中使用。

6.5函數(shù)與數(shù)組

6.5.1函數(shù)和一維數(shù)組1.一維數(shù)組元素作為函數(shù)的實參由于數(shù)組元素與相同類型的簡單變量地位完全一樣,因此,數(shù)組元素作為函數(shù)參數(shù)也和簡單變量一樣,采用值的單向傳遞方式。

例6-17用一維數(shù)組score存放一學(xué)生6門課程的成績,并將成績依次輸出。

2.數(shù)組名作為實參、形參

前面已經(jīng)介紹過,在一維數(shù)組中,用“數(shù)組名[下標]”表示的數(shù)組元素相當于一個普通變量;而不帶下標的數(shù)組名代表一批變量,也可以把它看成一個特殊的變量,因為它存

放該數(shù)組的首地址(即數(shù)組首元素的地址)。

在函數(shù)中,直接用數(shù)組名作為參數(shù)時,則傳送的是地址值,即把實參數(shù)組的首地址傳

遞給形參數(shù)組,而不是將全部數(shù)組元素都復(fù)制到函數(shù)中去。地址傳遞后,實參數(shù)組、形參數(shù)組地址相同,共享相同的內(nèi)存單元,也就是說形參數(shù)組和實參數(shù)組其實就是同一個數(shù)組,只是它們的生存期與作用域不同而已。

例6-18有一個一維數(shù)組score,存放一個學(xué)生6門課程的成績,求平均成績。

在本例中,實參數(shù)組名為score,形參數(shù)組名為array。在主程序的函數(shù)調(diào)用average(score)時,實參數(shù)組score[6]通過數(shù)組名score把首地址傳給array后,則array和score共享實參數(shù)組所占用的內(nèi)存空間,也就是說形參數(shù)組array和實參數(shù)組score其實就是同一個數(shù)組,只不過是有兩個名字而已,如圖6-9所示。

圖6-9數(shù)組array和數(shù)組score共享相同的內(nèi)存空間

編譯系統(tǒng)對形參數(shù)組大小不進行檢查,因此形參數(shù)組可以不指定大小,在數(shù)組名后跟一對空的方括號即可,即其大小由相應(yīng)的實參數(shù)組決定。在調(diào)用時將實參數(shù)組的首地址傳給形參數(shù)組,也就是說,形參數(shù)組并不在內(nèi)存中重新申請數(shù)組的空間,而是和實參數(shù)組共享存儲單元。但要注意,實參數(shù)組和形參數(shù)組類型應(yīng)保持一致。如在上例中,實參數(shù)組score和形參數(shù)組array的元素類型都為float類型。

例6-19從鍵盤輸入一字符串,判斷字符串長度并輸出(不使用strlen()函數(shù))。

例6-20把一個數(shù)字字符串轉(zhuǎn)換成長整型數(shù)(不使用atol()函數(shù))。

本節(jié)在分析函數(shù)調(diào)用過程的參數(shù)傳遞問題時,特別強調(diào)要區(qū)分實參向形參傳遞的是“值”還是“地址”。嚴格說來,“地址”也是值(地址值),但通過前面兩個例子的分析可以看出,它們有一個顯著的區(qū)別:即“值傳遞”在實參將“值”傳遞給形參后,對形參的修改不會影響到對應(yīng)的實參,這可以理解為實參和形參各自占用不同的存儲空間,實參在將“值”傳遞給形參后,二者就脫離關(guān)系了;而“地址傳遞”在實參將“地址”值傳遞給形參后,形參就和實參共享同一存儲區(qū),而不另外分配存儲空間,這可以理解為形參名和實參名只是同一存儲單元的兩個不同名稱而已,

溫馨提示

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

評論

0/150

提交評論