C語(yǔ)言程序設(shè)計(jì) 課件 (張惠濤 )第5、6章 函數(shù)、指針_第1頁(yè)
C語(yǔ)言程序設(shè)計(jì) 課件 (張惠濤 )第5、6章 函數(shù)、指針_第2頁(yè)
C語(yǔ)言程序設(shè)計(jì) 課件 (張惠濤 )第5、6章 函數(shù)、指針_第3頁(yè)
C語(yǔ)言程序設(shè)計(jì) 課件 (張惠濤 )第5、6章 函數(shù)、指針_第4頁(yè)
C語(yǔ)言程序設(shè)計(jì) 課件 (張惠濤 )第5、6章 函數(shù)、指針_第5頁(yè)
已閱讀5頁(yè),還剩109頁(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)介

第5章

函數(shù)函數(shù)

6C語(yǔ)言程序的開(kāi)發(fā)環(huán)境5.1模塊化程序設(shè)計(jì)與函數(shù)5.2函數(shù)定義5.3函數(shù)調(diào)用5.4函數(shù)遞歸調(diào)用5.5變量的作用域與儲(chǔ)存期5.6編譯預(yù)處理5.1模塊化程序設(shè)計(jì)與函數(shù)

在設(shè)計(jì)較復(fù)雜的程序時(shí),一般采用自頂向下的方法,將問(wèn)題劃分為幾個(gè)部分,各個(gè)部分再進(jìn)行細(xì)化,直到分解為很容易求解的小問(wèn)題為止。求解小問(wèn)題的程序算法叫做“功能模塊”,把復(fù)雜的問(wèn)題分解為單獨(dú)的模塊后,稱為模塊化設(shè)計(jì)。因此C語(yǔ)言程序設(shè)計(jì)是模塊化程序設(shè)計(jì)。5.1.1模塊與函數(shù)C語(yǔ)言中程序是由基本語(yǔ)句和函數(shù)組成,每個(gè)函數(shù)負(fù)責(zé)完成獨(dú)立的小任務(wù)。c語(yǔ)言程序設(shè)計(jì)是模塊化程序設(shè)計(jì)。任務(wù)、模塊和函數(shù)的關(guān)系是:解決整個(gè)特定問(wèn)題的大任務(wù)被分解成若干個(gè)小問(wèn)題即功能模塊,功能模塊由一個(gè)或者多個(gè)函數(shù)來(lái)具體實(shí)現(xiàn)。解決整個(gè)特定問(wèn)題的程序就通過(guò)這些函數(shù)的調(diào)用來(lái)完成??偨Y(jié)來(lái)說(shuō),模塊化程序設(shè)計(jì)就是由設(shè)計(jì)函數(shù)和調(diào)用函數(shù)來(lái)實(shí)現(xiàn)。5.1.1模塊與函數(shù)編程輸出以下圖形。

*********團(tuán)結(jié)就是力量!*********方法一:(不用函數(shù)實(shí)現(xiàn)的程序源代碼)#include<bits/stdc++.h>intmain(){ printf("*********\n"); printf("團(tuán)結(jié)就是力量!\n"); printf("*********\n"); }【例5.1】5.1.1模塊與函數(shù)方法二:(用函數(shù)實(shí)現(xiàn)的程序源代碼)#include<bits/stdc++.h>intmain(){ voidprintstar();/*對(duì)printstar函數(shù)進(jìn)行聲明*/ voidprintunity();/*對(duì)printhelloworld函數(shù)進(jìn)行聲明*/ printstar();/*調(diào)用printstar函數(shù)*/ printunity();/*調(diào)用printhelloworld函數(shù)*/ printstar();/*調(diào)用printstar函數(shù)*/}voidprintstar(){/*定義printstar函數(shù)*/ printf("*********\n");}voidprintunity(){/*定義printhelloworld函數(shù)*/ printf("團(tuán)結(jié)就是力量!\n");}5.1.2模塊化設(shè)計(jì)的基本原則

1.模塊獨(dú)立模塊完成獨(dú)立的功能,和其他模塊間的關(guān)系簡(jiǎn)單,各模塊可以單獨(dú)調(diào)試。修改某一模塊,不會(huì)造成整個(gè)程序的混亂。

模塊的獨(dú)立性原則是指模塊完成獨(dú)立的功能,可單獨(dú)進(jìn)行調(diào)試。各個(gè)模塊之間的聯(lián)系簡(jiǎn)單,修改一個(gè)模塊不會(huì)對(duì)整個(gè)程序產(chǎn)生大的影響。這要求我們?cè)谀K設(shè)計(jì)中注意幾個(gè)問(wèn)題:首先,因?yàn)槟K具有相對(duì)獨(dú)立性,所以在分解任務(wù)時(shí)要注意對(duì)問(wèn)題的綜合。其次,各個(gè)模塊之間的聯(lián)系簡(jiǎn)單,盡量只包含簡(jiǎn)單的數(shù)據(jù)傳遞這種聯(lián)系,不要涉及到控制聯(lián)系。最后要注意模塊的私有數(shù)據(jù)的使用。5.1.2模塊設(shè)計(jì)原則

2.模塊規(guī)模適當(dāng)

模塊的規(guī)模不能太大或者太小。功能太強(qiáng)的模塊,一般可讀性就會(huì)很差,功能太小的模塊,會(huì)出現(xiàn)很多接口。初學(xué)者只需記住此原則,在以后的實(shí)踐中需經(jīng)常總結(jié)經(jīng)驗(yàn)。

3.分解模塊要注意層次

在對(duì)任務(wù)進(jìn)行多層次分解時(shí),要尤其注意對(duì)問(wèn)題進(jìn)行抽象化。開(kāi)始只需考慮大的模塊,不要過(guò)分注意細(xì)節(jié)。在中期,大模塊的設(shè)計(jì)中,再逐步細(xì)化求精,分解成較小的模塊進(jìn)行設(shè)計(jì)。5.2函數(shù)定義

在C語(yǔ)言中,函數(shù)(Function)是一個(gè)處理過(guò)程,把一段程序的工作放在函數(shù)中進(jìn)行,函數(shù)結(jié)束時(shí)可以攜帶或不帶處理結(jié)果。C語(yǔ)言中的程序處理過(guò)程全部都是以函數(shù)形式出現(xiàn),最簡(jiǎn)單的程序至少也包含一個(gè)main()函數(shù)。函數(shù)必須先定義和聲明后才能調(diào)用。5.2函數(shù)定義用戶使用的函數(shù)通常有兩種:標(biāo)準(zhǔn)庫(kù)函數(shù)和自定義函數(shù)。標(biāo)準(zhǔn)庫(kù)函數(shù):是系統(tǒng)提供給用戶,c語(yǔ)言的強(qiáng)大功能依賴于它豐富的庫(kù)函數(shù)。需要注意的是,如果用戶想調(diào)用這些函數(shù),則必須先用編譯預(yù)處理命令將相應(yīng)的頭文件包含到程序中。在前面各章的例題中反復(fù)用到printf、scanf、getchar、putchar、gets、puts、strcat等函數(shù)均屬此類。自定義函數(shù):用戶自己編寫(xiě)。不僅要在程序中定義函數(shù)本身,而且在主調(diào)函數(shù)模塊中還必須對(duì)該被調(diào)函數(shù)進(jìn)行類型說(shuō)明,然后才能使用。5.2.1函數(shù)定義的一般形式函數(shù)的定義就是把子任務(wù)的程序?qū)懙揭粋€(gè)函數(shù)里。函數(shù)包含函數(shù)的說(shuō)明部分和函數(shù)體兩大部分。一般形式:類型名函數(shù)名(參數(shù)類型說(shuō)明及列表)

{局部變量說(shuō)明語(yǔ)句序列

}例如:輸入兩個(gè)整數(shù),以下函數(shù)minpear輸出兩個(gè)數(shù)中較小者:intminpear(inta,intb)/*函數(shù)定義和形式參數(shù)類型說(shuō)明*/{intt;/*局部變量說(shuō)明*/if(a<b)t=a;/*執(zhí)行語(yǔ)句*/elset=b;returnt;/*返回語(yǔ)句*/}

1.函數(shù)的說(shuō)明部分函數(shù)的說(shuō)明部分包括函數(shù)的類型、函數(shù)名、參數(shù)表和參數(shù)類型的說(shuō)明。例如上例中第一行為函數(shù)的說(shuō)明部分。(1)函數(shù)的類型。即函數(shù)的返回值類型。表示給調(diào)用者提供什么類型的返回值。函數(shù)可以有或者沒(méi)有返回值。

如果函數(shù)沒(méi)有返回值,則定義函數(shù)類型為空,用標(biāo)識(shí)符void表示空類型。例如:voiddata(inta)

如果函數(shù)有返回值,例如上例中min函數(shù)的類型為int,即函數(shù)的返回值類型是int。(2)函數(shù)名。也叫函數(shù)標(biāo)識(shí)符。它遵循C語(yǔ)句標(biāo)識(shí)符的命名規(guī)范。(3)參數(shù)表。函數(shù)名后面的括號(hào)“()”里的內(nèi)容是參數(shù)表,由變量標(biāo)識(shí)符和類型標(biāo)識(shí)符構(gòu)成。參數(shù)表中的變量也叫作形式參數(shù),即形參。5.2.1函數(shù)定義的一般形式

1.函數(shù)的說(shuō)明部分

根據(jù)參數(shù)表中是否有參數(shù)可將函數(shù)分為無(wú)參函數(shù)和有參函數(shù)。無(wú)參函數(shù):函數(shù)可以沒(méi)有形參,叫作無(wú)參函數(shù),注意無(wú)參函數(shù)的括號(hào)“()”不能省略。有參函數(shù):如果有形參,在定義形參時(shí),必須指定形參的類型。例如:intmin(inta,intb)5.2.1函數(shù)定義的一般形式

2.函數(shù)體

在函數(shù)定義中,函數(shù)體是用花括號(hào)括起來(lái)的部分,函數(shù)的具體功能在函數(shù)體中完成。函數(shù)體內(nèi)的開(kāi)頭部分是定義和說(shuō)明部分,后面是語(yǔ)句部分。函數(shù)聲明和函數(shù)體構(gòu)成了函數(shù)定義。

函數(shù)的返回值,是指函數(shù)被調(diào)用之后,執(zhí)行函數(shù)體中的程序段后得到的結(jié)果,并返回給主調(diào)函數(shù)。關(guān)于函數(shù)的返回值有下面幾點(diǎn)說(shuō)明:

(1)有返回值的函數(shù)體:需要有return返回語(yǔ)句。格式如下:return(表達(dá)式);該語(yǔ)句的執(zhí)行順序是先計(jì)算表達(dá)式的值,然后把結(jié)果返回給主調(diào)函數(shù)。

(2)return語(yǔ)句表達(dá)式的類型要和函數(shù)定義中函數(shù)的類型保持一致。如果不一致,則以函數(shù)的類型為準(zhǔn),自動(dòng)進(jìn)行類型轉(zhuǎn)換。

(3)若函數(shù)類型為整型,則函數(shù)定義時(shí)可以省略函數(shù)類型。

例如,上面提到的自定義函數(shù)min(a,b),根據(jù)傳入的a和b兩個(gè)值的大小返回一個(gè)t值,也就是兩個(gè)數(shù)中的較小者。5.2.1函數(shù)定義的一般形式

函數(shù)調(diào)用時(shí),應(yīng)該遵循先定義后使用的原則。如果函數(shù)調(diào)用出現(xiàn)在函數(shù)定義之前,則要對(duì)函數(shù)先進(jìn)行聲明,也就是讓系統(tǒng)先知道要用哪個(gè)函數(shù)以及函數(shù)類型等信息。5.3函數(shù)調(diào)用

函數(shù)聲明與函數(shù)定義時(shí)的第一行是基本一致的,包括函數(shù)類型、函數(shù)名、形參個(gè)數(shù)、類型、次序。不同的是,函數(shù)聲明是函數(shù)定義時(shí)的第一行在結(jié)尾時(shí)加上“;”,并且參數(shù)列表中可以省略參數(shù)名。

格式如下:

類型名函數(shù)名(參數(shù)類型說(shuō)明列表);5.3.1函數(shù)的聲明5.3.1函數(shù)的聲明編程實(shí)現(xiàn)孔融讓梨,輸出較小的梨。步驟分析:輸入兩個(gè)整數(shù),表示梨的重量;調(diào)用函數(shù)minpear()進(jìn)行較小值的比較運(yùn)算;輸出運(yùn)算結(jié)果;Intmain(){ intminpear(inta,intb);/*對(duì)minpear函數(shù)的聲明*/ intx,y,z; printf("inputtwonumbers:\n"); scanf("%d%d",&x,&y); z=minpear(x,y);/*調(diào)用minpear函數(shù)*/ printf("minmum=%d",z);#include<bits/stdc++.h>intminpear(inta,intb){/*函數(shù)定義和形式參數(shù)類型說(shuō)明*/ intt;/*局部變量說(shuō)明*/ if(a<b)t=a;/*執(zhí)行語(yǔ)句*/ elset=b; returnt;/*返回語(yǔ)句*/}【例5.2】5.3.1函數(shù)的聲明

本例中,把x,y中的值傳送給minpear的形參a,b。minpear函數(shù)執(zhí)行的結(jié)果(a或b)將返回給變量z。最后由主函數(shù)輸出z的值。

注意:孔融讓梨程序運(yùn)行結(jié)果如圖:

根據(jù)函數(shù)有參數(shù)或者無(wú)參數(shù)兩種情況,函數(shù)調(diào)用可分為:有參函數(shù)調(diào)用和無(wú)參函數(shù)調(diào)用。1、有參函數(shù)調(diào)用的形式:函數(shù)名(實(shí)參表達(dá)式)

例如:min(inta,intb);2、無(wú)參函數(shù)調(diào)用的形式:函數(shù)名()

例如:func();5.3.2函數(shù)的調(diào)用

根據(jù)調(diào)用方式不同,函數(shù)調(diào)用可分為:語(yǔ)句調(diào)用和表達(dá)式調(diào)用1、語(yǔ)句調(diào)用的形式:

例如:scanf(“%d”,&x);2、表達(dá)式調(diào)用的形式:

例如:a+min(x,y);5.3.3函數(shù)的嵌套調(diào)用

在C語(yǔ)言中不允許“嵌套定義函數(shù)”,即不能在一個(gè)函數(shù)的定義中作另一個(gè)函數(shù)的定義。例如下面的例子,在main函數(shù)的定義中作printdata函數(shù)的定義,這種寫(xiě)法是錯(cuò)誤的:intmain(intargc,char*argv[]){//定義func函數(shù)voidprintdata(inta){printf("inprintdata,a=%d\n",a);}printdata(8);return0;}

這樣的代碼,在VC編譯器,或者VisualStudio編譯器中,屬于非法定義的代碼。雖然在func函數(shù)的調(diào)用之前,定義了func函數(shù)。但是,不能夠在main函數(shù)中定義func函數(shù),就是不能夠嵌套定義函數(shù)。

注意:5.3.3函數(shù)的嵌套調(diào)用

但是C語(yǔ)言允許在一個(gè)函數(shù)的定義中出現(xiàn)對(duì)另一個(gè)函數(shù)的調(diào)用。這叫作函數(shù)的嵌套調(diào)用。也就是在被調(diào)函數(shù)中又調(diào)用其它函數(shù)。這與其它語(yǔ)言的子程序嵌套的情形是類似的。例如:intb()/*定義函數(shù)b*/{…….}inta()/*定義函數(shù)a*/{…….b();/*a中調(diào)用函數(shù)b*/}voidmain(){……a();/*主函數(shù)中調(diào)用函數(shù)a*/}調(diào)用a()f2()調(diào)用b()main()b()5.3.3函數(shù)的嵌套調(diào)用

圖中表示了兩層嵌套的情況。其執(zhí)行過(guò)程是:在執(zhí)行main函數(shù)時(shí)遇到了調(diào)用a函數(shù)的語(yǔ)句,即轉(zhuǎn)到a函數(shù)去執(zhí)行,在執(zhí)行a函數(shù)時(shí)遇到了調(diào)用b函數(shù)的語(yǔ)句,則轉(zhuǎn)到b函數(shù)去執(zhí)行,當(dāng)b函數(shù)執(zhí)行完畢后返回a函數(shù)的斷點(diǎn)繼續(xù)執(zhí)行,a函數(shù)執(zhí)行完畢后返回main函數(shù)的斷點(diǎn)繼續(xù)執(zhí)行。5.3.3函數(shù)的嵌套調(diào)用

學(xué)校為鼓勵(lì)學(xué)生和輔導(dǎo)老師以賽促教、以賽促學(xué)、以賽促改,進(jìn)一步推進(jìn)學(xué)校創(chuàng)新創(chuàng)業(yè)教育邁上新臺(tái)階,要求統(tǒng)計(jì)計(jì)算機(jī)專業(yè)兩個(gè)班的大學(xué)生計(jì)算機(jī)應(yīng)用能力競(jìng)賽獲獎(jiǎng)人數(shù),學(xué)校把任務(wù)分配給了輔導(dǎo)員,輔導(dǎo)員把任務(wù)分配給了班長(zhǎng)。試編程實(shí)現(xiàn)。代碼設(shè)計(jì)如下:#include<bits/stdc++.h>intmain(){ intcounselor(); printf("%d",counselor());}intcounselor(){ intmonitor(); return(monitor());}intmonitor(){ inta,b; scanf("%d,%d",&a,&b); returna+b;}【例5.3】5.3.3函數(shù)的嵌套調(diào)用大學(xué)生計(jì)算機(jī)應(yīng)用能力競(jìng)賽獲獎(jiǎng)人數(shù)程序運(yùn)行結(jié)果如圖:main函數(shù)相當(dāng)于學(xué)校,在輸出函數(shù)中調(diào)用counselor函數(shù)。counselor函數(shù)中,在return語(yǔ)句中調(diào)用了monitor函數(shù),monitor函數(shù)來(lái)求兩個(gè)班的人數(shù),并且通過(guò)return語(yǔ)句返回人數(shù)之和,層層返回。5.3.3函數(shù)的嵌套調(diào)用【例5.4】計(jì)算s=12!+22!+32!#include<bits/stdc++.h>longf1(intd){ /*定義求立方值的函數(shù)f1*/ intcube; longr; longf2(int); /*嵌套調(diào)用階乘函數(shù)f2*/ cube=d*d; r=f2(cube); returnr;}

解題思路:本題可通過(guò)編寫(xiě)兩個(gè)函數(shù)來(lái)實(shí)現(xiàn),第一個(gè)函數(shù)f1用來(lái)實(shí)現(xiàn)計(jì)算平方值,第二個(gè)函數(shù)f2用來(lái)實(shí)現(xiàn)計(jì)算階乘值。代碼設(shè)計(jì)如下:5.3.3函數(shù)的嵌套調(diào)用longf2(intq){ /*定義求階乘值的函數(shù)f2*/ longc=1; inti; for(i=1;i<=q;i++) c=c*i; returnc;}main(){ inti; longs=0; for(i=1;i<=3;i++) s=s+f1(i); /*調(diào)用求立方值的函數(shù)f1*/ printf("\ns=%ld\n",s);}5.3.4參數(shù)傳遞

形參出現(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ù)傳送。

5.3.4參數(shù)傳遞

函數(shù)的形參和實(shí)參具有以下特點(diǎn):1、形參變量只有在被調(diào)用時(shí)才分配內(nèi)存單元,在調(diào)用結(jié)束時(shí),即刻釋放所分配的內(nèi)存單元。因此,形參只有在函數(shù)內(nèi)部有效。函數(shù)調(diào)用結(jié)束返回主調(diào)函數(shù)后則不能再使用該形參變量。2、實(shí)參可以是常量、變量、表達(dá)式、函數(shù)等,無(wú)論實(shí)參是何種類型的量,在進(jìn)行函數(shù)調(diào)用時(shí),它們都必須具有確定的值,以便把這些值傳送給形參。因此應(yīng)預(yù)先用賦值,輸入等辦法使實(shí)參獲得確定值。3、實(shí)參和形參在數(shù)量上,類型上,順序上應(yīng)嚴(yán)格一致,否則會(huì)發(fā)生類型不匹配”的錯(cuò)誤。4、函數(shù)調(diào)用中發(fā)生的數(shù)據(jù)傳送是單向的。即只能把實(shí)參的值傳送給形參,而不能把形參的值反向地傳送給實(shí)參。因此在函數(shù)調(diào)用過(guò)程中,形參的值發(fā)生改變,而實(shí)參中的值不會(huì)變化。5.3.4參數(shù)傳遞【例5.5】參數(shù)傳遞算法實(shí)例。#include<bits/stdc++.h>intmain(){ intn; printf("inputnumber\n"); scanf("%d",&n); ints(intn); s(n); printf("n=%d\n",n);}ints(intn){ inti; for(i=n-1;i>=1;i--) n=n+i; printf("n=%d\n",n);}5.3.4參數(shù)傳遞

本程序中定義了一個(gè)函數(shù)s,該函數(shù)的功能是求n+(n-1)+….+1的值。在主函數(shù)中輸入n值,并作為實(shí)參,在調(diào)用時(shí)傳送給s函數(shù)的形參量n(注意,本例的形參變量和實(shí)參變量的標(biāo)識(shí)符都為n,但這是兩個(gè)不同的量,各自的作用域不同)。

在主函數(shù)中用printf語(yǔ)句輸出一次n值,這個(gè)n值是實(shí)參n的值。在函數(shù)s中也用printf語(yǔ)句輸出了一次n值,這個(gè)n值是形參最后取得的n值0。從運(yùn)行情況看,輸入n值為10。即實(shí)參n的值為10。把此值傳給函數(shù)s時(shí),形參n的初值也為10,在執(zhí)行函數(shù)過(guò)程中,形參n的值變?yōu)?5。返回主函數(shù)之后,輸出實(shí)參n的值仍為10??梢?jiàn)實(shí)參的值不隨形參的變化而變化。5.4函數(shù)遞歸調(diào)用直接遞歸形式如下:voidfunc(){......func();/*函數(shù)func中調(diào)用函數(shù)func,直接遞歸*/......}

在函數(shù)內(nèi)部調(diào)用自己,叫作函數(shù)的遞歸調(diào)用。遞歸調(diào)用分為直接遞歸和間接遞歸。

某一函數(shù)在函數(shù)體內(nèi)部直接調(diào)用自身函數(shù)叫作函數(shù)的直接遞歸。即函數(shù)的嵌套調(diào)用的是函數(shù)本身。嵌套調(diào)用自身函數(shù)在我們的學(xué)習(xí)生活中就好像是榜樣的示范!修身立德,才能言傳身教,彰顯榜樣力量!

某一函數(shù)在函數(shù)體內(nèi)部調(diào)用其他函數(shù),其他函數(shù)再調(diào)用本函數(shù),叫作函數(shù)的間接遞歸。5.4函數(shù)遞歸調(diào)用(2)間接遞歸形式如下:voidfunc1(){......func2();/*函數(shù)func1中調(diào)用函數(shù)func2*/......}voidfunc2(){......func1();/*函數(shù)func2中調(diào)用函數(shù)func1,間接遞歸*/

遞歸思想是一個(gè)非常有用的解決問(wèn)題的思路。它不僅可以解決本身是遞歸定義的問(wèn)題,還可以把看起來(lái)很復(fù)雜不容易描述出來(lái)的過(guò)程變得簡(jiǎn)單明了。下面針對(duì)這兩方面分別舉例說(shuō)明遞歸思想。5.4函數(shù)遞歸調(diào)用【例5.6】用遞歸算法計(jì)算n!由于n!=n*(n-1)!是遞歸定義,所以求n!

(n-1)!

(n-1)!

(n-2)!

(n–2)!

(n-3)!

……

0!的問(wèn)題,

根據(jù)公式有0!=1,

再反過(guò)來(lái)依次求出1!,2!……直到最后求出n!。5.4函數(shù)遞歸調(diào)用#include<stdio.h>longfac(intn){longf;if(n<0)printf("n<0,inputerror");elseif(n==0||n==1)f=1;elsef=fac(n-1)*n;return(f);}intmain(){intn;longy;printf("\ninputainteagernumber:\n");scanf("%d",&n);y=fac(n);printf("%d!=%ld",n,y);}直到最后的fac(n)都做完了,f的值被返回到了它的調(diào)用點(diǎn):主函數(shù)中,這樣就是一個(gè)遞歸運(yùn)算。

程序中給出的函數(shù)fac是一個(gè)遞歸函數(shù)。主函數(shù)調(diào)用fac后即執(zhí)行函數(shù)fac,如果n<0,n==0或n=1時(shí)都將結(jié)束函數(shù)的執(zhí)行,否則就遞歸調(diào)用fac函數(shù)自身。注意每次遞歸調(diào)用的實(shí)參為n-1,即把n-1的值賦予形參n,最后當(dāng)n-1的值為1時(shí)再作遞歸調(diào)用,形參n的值也為1,將使遞歸終止。然后可逐層退回。5.4函數(shù)遞歸調(diào)用

運(yùn)行上述程序,若輸入為5,則求5!。在主函數(shù)中調(diào)用語(yǔ)句y=fac(5),進(jìn)入fac函數(shù)執(zhí)行,判斷n=5,不滿足n等于0或1,故應(yīng)該執(zhí)行f=fac(n-1)*n,即f=fac(5-1)*5。此語(yǔ)句為遞歸調(diào)用。轉(zhuǎn)為求fac(4)。進(jìn)行四次遞歸調(diào)用后,fac函數(shù)的形參變?yōu)?,滿足elseif(n==0||n==1),將結(jié)束函數(shù)的執(zhí)行,故不再進(jìn)行遞歸調(diào)用,而開(kāi)始逐層返回主調(diào)函數(shù)。fac(1)的函數(shù)返回值為1,fac(2)的返回值為1*2=2,fac(3)的返回值為2*3=6,fac(4)的返回值為6*4=24,最后返回值fac(5)為24*5=120。遞歸算法程序運(yùn)行結(jié)果如圖所示:5.4函數(shù)遞歸調(diào)用

【例5.7】漢諾塔游戲是理論指導(dǎo)實(shí)踐,鍛煉學(xué)生們動(dòng)手操作的經(jīng)典游戲,請(qǐng)編程實(shí)現(xiàn)。漢諾塔是一個(gè)很繁雜的游戲,但可以用遞歸的方法異常簡(jiǎn)單的完成。規(guī)則:(1)一次只能移動(dòng)一個(gè)金片。

(2)大的不能放在小的上面。

(3)只能在三個(gè)位置中移動(dòng)??傮w思想:1.將i-1個(gè)盤(pán)子先放到B座位上。2.將A座上地剩下的一個(gè)盤(pán)移動(dòng)到C盤(pán)上。3.將i-1個(gè)盤(pán)從B座移動(dòng)到C座上。5.4函數(shù)的遞歸調(diào)用遞歸法解漢諾塔#include<bits/stdc++.h>voidhanoi(intn,inta,intb,intc)

{

if(n==1)

printf(“%d->%d”,a,c);

else

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

printf(“%d->%d”,a,c);

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

}

}voidmain()

{intn;

printf(“inputn:”);

scanf(“%d”,&n);

hanoi(n,1,2,3);

}再將n-1個(gè)盤(pán)子從b經(jīng)過(guò)a移動(dòng)到cn=1時(shí),直接將金片從a移動(dòng)到cn-1個(gè)金片從a經(jīng)過(guò)c移動(dòng)到b5.4函數(shù)的遞歸調(diào)用voidhanoi(intn,inta,intb,intc)

{

if(n==1)

printf(“%d->%d”,a,c);

else

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

printf(“%d->%d”,a,c);

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

}

}voidmain()

{intn;

printf(“inputn:”);

scanf(“%d”,&n);

hanoi(n,1,2,3);

}遞歸解漢諾塔步驟輸入3,則n=35.4函數(shù)的遞歸調(diào)用voidhanoi(intn,inta,intb,intc)

{

if(n==1)

printf(“%d->%d”,a,c);

else

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

printf(“%d->%d”,a,c);

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

}

}voidmain()

{intn;

printf(“inputn:”);

scanf(“%d”,&n);

hanoi(n,1,2,3);

}遞歸解漢諾塔步驟n=3

主函數(shù)調(diào)用hanoi(n,1,2,3);第一次調(diào)用。第一次調(diào)用hanoi(n,a,b,c)(第一層)即要把三個(gè)金片移到c5.4函數(shù)的遞歸調(diào)用遞歸解漢諾塔步驟voidhanoi(intn,inta,intb,intc)

{

if(n==1)

printf(“%d->%d”,a,c);

else

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

printf(“%d->%d”,a,c);

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

}

}voidmain()

{intn;

printf(“inputn:”);

scanf(“%d”,&n);

hanoi(n,1,2,3);

}由于n>1則執(zhí)行hanoi(n-1,a,c,b)

(第二次調(diào)用)n=35.4函數(shù)的遞歸調(diào)用遞歸解漢諾塔步驟voidhanoi(intn,inta,intb,intc)

{

if(n==1)

printf(“%d->%d”,a,c);

else

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

printf(“%d->%d”,a,c);

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

}

}voidmain()

{intn;

printf(“inputn:”);

scanf(“%d”,&n);

hanoi(n,1,2,3);

}由于仍然n>1則執(zhí)行hanoi(n-1,a,c,b)

(第三次調(diào)用)5.4函數(shù)的遞歸調(diào)用遞歸解漢諾塔步驟voidhanoi(intn,inta,intb,intc)

{

if(n==1)

printf(“%d->%d”,a,c);

else

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

printf(“%d->%d”,a,c);

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

}

}voidmain()

{intn;

printf(“inputn:”);

scanf(“%d”,&n);

hanoi(n,1,2,3);

}n=2第三層執(zhí)行完畢,返回到第二層,即下去執(zhí)行printf(“%d->%d”,a,c);把第二個(gè)金片擺到第二根針上5.4函數(shù)的遞歸調(diào)用遞歸解漢諾塔步驟voidhanoi(intn,inta,intb,intc)

{

if(n==1)

printf(“%d->%d”,a,c);

else

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

printf(“%d->%d”,a,c);

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

}

}voidmain()

{intn;

printf(“inputn:”);

scanf(“%d”,&n);

hanoi(n,1,2,3);

}n=2執(zhí)行下一條語(yǔ)句,又調(diào)用第三層hanoi(1,3,1,2)5.4函數(shù)的遞歸調(diào)用遞歸解漢諾塔步驟voidhanoi(intn,inta,intb,intc)

{

if(n==1)

printf(“%d->%d”,a,c);

else

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

printf(“%d->%d”,a,c);

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

}

}voidmain()

{intn;

printf(“inputn:”);

scanf(“%d”,&n);

hanoi(n,1,2,3);

}n=1n=1,執(zhí)行結(jié)果為3

25.4函數(shù)的遞歸調(diào)用遞歸解漢諾塔步驟voidhanoi(intn,inta,intb,intc)

{

if(n==1)

printf(“%d->%d”,a,c);

else

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

printf(“%d->%d”,a,c);

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

}

}voidmain()

{intn;

printf(“inputn:”);

scanf(“%d”,&n);

hanoi(n,1,2,3);

}n=3第二層也執(zhí)行完了,返回第一層,執(zhí)行接下來(lái)的語(yǔ)句,結(jié)果為1

3。5.4函數(shù)的遞歸調(diào)用遞歸解漢諾塔步驟voidhanoi(intn,inta,intb,intc)

{

if(n==1)

printf(“%d->%d”,a,c);

else

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

printf(“%d->%d”,a,c);

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

}

}voidmain()

{intn;

printf(“inputn:”);

scanf(“%d”,&n);

hanoi(n,1,2,3);

}n=3執(zhí)行接下來(lái)的語(yǔ)句,再次調(diào)用

第二層hanoi(2,2,1,3)5.4函數(shù)的遞歸調(diào)用遞歸解漢諾塔步驟voidhanoi(intn,inta,intb,intc)

{

if(n==1)

printf(“%d->%d”,a,c);

else

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

printf(“%d->%d”,a,c);

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

}

}voidmain()

{intn;

printf(“inputn:”);

scanf(“%d”,&n);

hanoi(n,1,2,3);

}5.5變量的作用域與儲(chǔ)存期

變量的作用域,即變量有效性的范圍。例如函數(shù)中的形參變量,只在函數(shù)調(diào)用時(shí)才給形參分配內(nèi)存單元,函數(shù)調(diào)用結(jié)束后該內(nèi)存單元就會(huì)被釋放。這說(shuō)明形參有效性的范圍即作用域是函數(shù)內(nèi)。形參在函數(shù)以外的范圍是不起作用的。C語(yǔ)言中的變量,根據(jù)作用域可劃分為兩類,即局部變量和全局變量。5.5.1變量根據(jù)作用域進(jìn)行劃分變量

局部變量也叫內(nèi)部變量。局部變量的作用域是函數(shù)內(nèi),即它是在函數(shù)內(nèi)作定義說(shuō)明的。函數(shù)以外的地方使用這種變量是不合法的。例如:voidfunc(){inta=3;c1+=32 c2+=32; c3+=32; c4+=32;}

在函數(shù)func中使用main函數(shù)中定義的局部變量c1,c2,c3和c4是非法的。c1,c2,c3和c4在main函數(shù)中定義說(shuō)明,只能在main函數(shù)中使用,即c1,c2,c3和c4的作用域僅限main函數(shù)。故在func函數(shù)中使用c1,c2,c3和c4是非法的。

1.局部變量voidmain(){charc1,c2,c3,c4; printf("Enterc1,c2,c3,c4:"); scanf("%c%c%c%c",&c1,&c2,&c3,&c4); func(); printf(“%c%c%c%c\n”,c1,c2,c3,c4);}5.5.1變量根據(jù)作用域進(jìn)行劃分變量正確的使用如下:【例5.8】#include<bits/stdc++.h>voidfunc(){ charc1,c2,c3,c4; /*定義函數(shù)func中的局部變量c1,c2,c3和c4*/ c1='A',c2='B',c3='C',c4='D’; c1+=32; c2+=32; c3+=32; c4+=32; printf("%c%c%c%c\n",c1,c2,c3,c4);/*輸出函數(shù)func中的c1,c2,c3和c4*/}intmain(){ charc1,c2,c3,c4; printf("Enterc1,c2,c3,c4:"); scanf("%c%c%c%c",&c1,&c2,&c3,&c4); func();/*調(diào)用函數(shù)func()*/ printf("%c%c%c%c\n",c1,c2,c3,c4);/*輸出main函數(shù)中的c1,c2,c3和c4*/}5.5.1變量根據(jù)作用域進(jìn)行劃分變量

全局變量也叫外部變量,它是在函數(shù)外部定義,其作用域是從定義開(kāi)始,到文件結(jié)束為止。對(duì)任何函數(shù)來(lái)說(shuō),它都不是局部的變量。全局變量具有全局作用域,即定義后,可以用在文件的所有函數(shù)中。如果要在函數(shù)中使用全局變量,應(yīng)先對(duì)全局變量進(jìn)行說(shuō)明。遵循先說(shuō)明后使用的原則。全局變量的說(shuō)明符為extern,可以省略。但是,如果全局變量的定義在前,函數(shù)內(nèi)使用全局變量在后,這種情況可不再加以說(shuō)明。

2.全局變量5.5.1變量根據(jù)作用域進(jìn)行劃分變量

2.全局變量【例5.9】全局變量在main函數(shù)中賦值并改變的實(shí)例。#include<bits/stdc++.h>charc1,c2,c3,c4; /*定義全局變量c1,c2,c3和c4*/voidfunc(){ c1+=32; /*使用全局變量在main函數(shù)中賦的值,并改變m和n的值*/ c2+=32; c3+=32; c4+=32; printf("%c%c%c%c\n",c1,c2,c3,c4);/*輸出已改變的c1,c2,c3和c4的值*/}intmain(){ c1='T',c2='E',c3='A',c4='M’; /*對(duì)全局變量c1,c2,c3和c4賦值*/ func(); /*調(diào)用函數(shù)func()*/ printf("%c%c%c%c\n",c1,c2,c3,c4);/*輸出c1,c2,c3和c4*/}5.5.2變量根據(jù)存儲(chǔ)方式進(jìn)行劃分

靜態(tài)存儲(chǔ)類型的變量的生存期為程序執(zhí)行的整個(gè)過(guò)程,在該過(guò)程中占有固定的存儲(chǔ)空間,通常稱它們?yōu)橛谰么鎯?chǔ)。變量按存儲(chǔ)方式劃分:—靜態(tài)存儲(chǔ)—?jiǎng)討B(tài)存儲(chǔ)說(shuō)明

動(dòng)態(tài)存儲(chǔ)類型變量只生存在某一段時(shí)間內(nèi)。例如,函數(shù)的形參和函數(shù)體或分程序中定義的變量,只是在程序進(jìn)入該函數(shù)或分程序時(shí)才分配存儲(chǔ)空間,當(dāng)該函數(shù)或分程序執(zhí)行完后,變量對(duì)應(yīng)的存儲(chǔ)空間又被撤銷(xiāo)。5.5.2變量根據(jù)存儲(chǔ)方式進(jìn)行劃分1、靜態(tài)存儲(chǔ)類別(1)全局變量

全局變量全部存放在靜態(tài)存儲(chǔ)區(qū),在程序開(kāi)始執(zhí)行時(shí)給全局變量分配存儲(chǔ)區(qū),程序執(zhí)行完畢就釋放內(nèi)存。全局變量占據(jù)固定的存儲(chǔ)單元,而不動(dòng)態(tài)地進(jìn)行分配和釋放;(2)靜態(tài)局部變量

靜態(tài)局部變量是用static聲明的局部變量,它屬于靜態(tài)存儲(chǔ)方式。局部變量的值在函數(shù)調(diào)用結(jié)束后釋放。有時(shí)希望保留函數(shù)中局部變量的原值,這種情況需要指定局部變量為“靜態(tài)局部變量”,用關(guān)鍵字static進(jìn)行聲明。例如:Staticintm,n;

注意:靜態(tài)局部變量在函數(shù)結(jié)束后仍保留原值,不隨函數(shù)的結(jié)束而消失,生存期為整個(gè)程序。靜態(tài)局部變量在編譯時(shí)賦初值,即只賦初值一次,若未賦初值,系統(tǒng)自動(dòng)賦值0.5.5.2變量根據(jù)存儲(chǔ)方式進(jìn)行劃分【例5.10】靜態(tài)局部變量實(shí)例。

#include<bits/stdc++.h>intfunc(){ staticintn=3; n*=2; return(n);}intmain(){ inti; for(i=0;i<3;i++) printf("%d\n",func());}5.5.2變量根據(jù)存儲(chǔ)方式進(jìn)行劃分2、動(dòng)態(tài)存儲(chǔ)類別動(dòng)態(tài)存儲(chǔ)方式:是在程序運(yùn)行期間根據(jù)需要給變量動(dòng)態(tài)的分配存儲(chǔ)空間。動(dòng)態(tài)存儲(chǔ)區(qū)存放函數(shù)的形式參數(shù)和auto自動(dòng)變量。auto自動(dòng)變量,是未加static聲明的局部變量。函數(shù)中的局部變量如果不加static存儲(chǔ)類別,都屬于動(dòng)態(tài)地分配存儲(chǔ)空間,數(shù)據(jù)存儲(chǔ)在動(dòng)態(tài)存儲(chǔ)區(qū)中。

函數(shù)中的形參和在函數(shù)中定義的變量都屬于自動(dòng)變量,在調(diào)用該函數(shù)時(shí)系統(tǒng)會(huì)給它們分配存儲(chǔ)空間,在函數(shù)調(diào)用結(jié)束時(shí)就自動(dòng)釋放這些存儲(chǔ)空間。自動(dòng)變量用關(guān)鍵字auto作存儲(chǔ)類別的聲明。形式如下:intf(inta)/*定義f函數(shù),a為參數(shù)*/{autointb,c=3;/*定義b,c自動(dòng)變量*/……}a是形參,b,c是自動(dòng)變量,對(duì)c賦初值3。執(zhí)行完f函數(shù)后,自動(dòng)釋放a,b,c所占的存儲(chǔ)單元。關(guān)鍵字auto可以省略,auto不寫(xiě)則隱含定為“自動(dòng)存儲(chǔ)類別”,屬于動(dòng)態(tài)存儲(chǔ)方式。5.6編譯預(yù)處理

“編譯預(yù)處理”是C語(yǔ)言編譯系統(tǒng)的一個(gè)組成部分。是在編譯前由編譯系統(tǒng)中的預(yù)處理程序?qū)υ闯绦虻念A(yù)處理命令進(jìn)行加工。

與源程序中的語(yǔ)句不同,源程序中的預(yù)處理命令以“#”開(kāi)頭,結(jié)束沒(méi)有分號(hào),它們可以放在程序中的任何位置,作用域是自出現(xiàn)點(diǎn)到源程序的末尾。

預(yù)處理命令包括執(zhí)行宏定義(宏替換)、文件包含和條件編譯。5.6.1宏定義無(wú)參宏的宏名后不帶參數(shù)。無(wú)參宏定義的一般形式為:#define標(biāo)識(shí)符字符串:其中,“#”表示該行為預(yù)處理命令,“define”為宏定義命令,“標(biāo)識(shí)符”為定義的宏名,這里為“M”,“字符串”可以是常數(shù)、表達(dá)式、格式串等。例如#defineM(x*x+3*x+1)定義后,可以用M來(lái)代替(x*x+3*x+1)。在編寫(xiě)源程序時(shí),所有的(x*x+3*x+1)都可由M代替,而對(duì)源程序作編譯時(shí),將先由預(yù)處理程序進(jìn)行宏代換,即用(x*x+3*x+1)表達(dá)式去置換所有的宏名M,然后再進(jìn)行編譯。

1.無(wú)參宏定義5.6.1宏定義【例5.11】無(wú)參宏定義算法實(shí)例。#include<bits/stdc++.h>#defineSENTENCE("IloveChina!")intmain(){ printf("%s",SENTENCE);}

1.無(wú)參宏定義5.6.1宏定義(1)宏定義是用宏名來(lái)表示一個(gè)字符串,在宏展開(kāi)時(shí)又以該字符串取代宏名,這只是一種簡(jiǎn)單的代換,字符串中可以含任何字符,可以是常數(shù),也可以是表達(dá)式,預(yù)處理程序?qū)λ蛔魅魏螜z查。如有錯(cuò)誤,只能在編譯已被宏展開(kāi)后的源程序時(shí)發(fā)現(xiàn)。(2)宏定義不是說(shuō)明或語(yǔ)句,在行末不必加分號(hào),如加上分號(hào)則連分號(hào)也一起置換。(3)宏定義必須寫(xiě)在函數(shù)之外,其作用域?yàn)楹甓x命令起到源程序結(jié)束。如要終止其作用域可使用#undef命令。說(shuō)明5.6.1宏定義一般形式:#define宏名(形參表)字符串

如:#defineS(a,b)a*b帶參宏調(diào)用的一般形式為:

宏名(實(shí)參表);例如:#defineM(x)x*x+3*x+1/*宏定義*/……k=M(8);/*宏調(diào)用*/……在宏調(diào)用時(shí),用實(shí)參8去代替形參x,經(jīng)預(yù)處理宏展開(kāi)后的語(yǔ)句為:k=8*8+3*8+1

2.帶參宏定義5.6.1宏定義【例5.12】商朝末年西周初年的數(shù)學(xué)家商高在公元前1000年發(fā)現(xiàn)勾股定理的一個(gè)特例:勾三,股四,弦五。早于意大利的數(shù)學(xué)家畢達(dá)哥拉斯發(fā)現(xiàn)此定理證明五百到六百年。試用帶參宏定義算法實(shí)現(xiàn)。

代碼如下:#include<bits/stdc++.h>#defineM(x,y)sqrt(x*x+y*y)intmain(){ ints; s=M(3,4); printf("s=%d\n",s);}

2.帶參宏定義5.6.2文件包含

文件包含是指一個(gè)源文件可以將另一個(gè)源文件的全部?jī)?nèi)容包含進(jìn)來(lái)。文件包含允許嵌套。

#include命令有兩種格式。

—#include<文件名>—#include“文件名”

兩種格式區(qū)別使用尖括號(hào)表示在包含文件目錄中查找(包含目錄是由用戶在設(shè)置環(huán)境時(shí)設(shè)置的),而不在源文件目錄查找;使用雙引號(hào)則表示首先在當(dāng)前的源文件目錄中查找,若未找到才到包含目錄中去查找。5.6.3條件編譯

按不同的條件去編譯不同的程序部分,即按照條件選擇源程序中的不同的語(yǔ)句參加編譯,因而產(chǎn)生不同的目標(biāo)代碼文件。這對(duì)于程序的移植和調(diào)試是很有用的。(1)#ifdef

標(biāo)識(shí)符程序段1

#else

程序段2

#endif

5.6.3條件編譯(2)#ifndef

標(biāo)識(shí)符

程序段1

#else

程序段2

#endif(3)#if

常量表達(dá)式程序段1

#else

程序段2

#endif

本章小結(jié)本章介紹了函數(shù)的模塊化程序設(shè)計(jì)思想和原則,函數(shù)的定義、函數(shù)的調(diào)用、函數(shù)的遞歸調(diào)用。詳述了變量的作用域和存儲(chǔ)方式,全局變量、局部變量、自動(dòng)變量和靜態(tài)變量的特點(diǎn)及應(yīng)用。還介紹了函數(shù)的編譯預(yù)處理功能,使程序更易于理解和移植。如果把程序比作大一生活,則可以把大一生活分成幾部分,每一部分都有獨(dú)立的事情要做,但這些融合到一起,才是多彩的大學(xué)生活。目錄1234指針與指針變量指針與數(shù)組指針與字符串指針與函數(shù)第6章指針5指針數(shù)組指針與指針變量6.16.1.1指針的概念地址:內(nèi)存單元的編號(hào)地址基本概念數(shù)據(jù)在內(nèi)存中的存儲(chǔ)定義變量-->分配內(nèi)存單元(變量名對(duì)應(yīng)其地址)-->賦值例如:inta=5;charch=‘s;…20005

a200120022003…4000sch內(nèi)存地址

數(shù)據(jù)的讀寫(xiě)根據(jù)變量的地址讀寫(xiě)內(nèi)存單元的內(nèi)容。6.1.1指針的概念…20003變量i20046變量j20089變量k…3010……內(nèi)存例如:inti=3,j=6,k;printf(“%d%d”,i,j);scanf(“%d”,&k);

變量的訪問(wèn)直接訪問(wèn):根據(jù)變量地址存取變量值間接訪問(wèn):根據(jù)指針存取變量值6.1.1指針的概念變量地址內(nèi)存單元指針變量地址內(nèi)存單元…20003變量i20046變量j20089變量k…30102000p…內(nèi)存例如:inti=3,j=6,k;printf(“%d”,i);int*p=&i;printf(“%d”,*p);

指針

(pointer)變量的地址6.1.1指針的概念例j=3;——直接訪問(wèn)指針變量…...…...4000400440064005整型變量j變量j_pointer40014002400340003例*j_pointer=10;——間接訪問(wèn)10指針和指針變量指向基本概念6.1.1指針的概念變量的指針:是一個(gè)變量的地址指針變量:用來(lái)存儲(chǔ)變量地址(指針)的變量變量的地址(指針)變量的內(nèi)存單元例如,若有inti=3;int*p=&i;則可以說(shuō)p指向變量i6.1.2

指針變量的定義與使用

1.指針變量的定義一般形式:

類型名

*指針變量名;例:int*p;float*q;char*r;(1)指針變量名是p,q,r,而不是*p,*q,*r;(2)類型名是指針?biāo)赶虻淖兞康臄?shù)據(jù)類型,指針變量只能指向定義時(shí)所規(guī)定類型的變量。(3)指針變量存放的是所指向的某個(gè)變量的地址值,而普通變量保存的是該變量本身的值。注意:

例如:inti=5;floatj=2.5;int*point;point=&i;(語(yǔ)法正確)point=&j;(語(yǔ)法錯(cuò)誤)6.1.2

指針變量的定義與使用

2.指針變量的使用兩個(gè)運(yùn)算符:&和*&:取地址運(yùn)算符,取變量的地址

一般形式為&變量名

例:int*p;//此處*表示p為指針類型

p=&a;*:指針運(yùn)算符,取指針?biāo)赶虻膬?nèi)容

一般形式為*指針變量名

例:*p=a;6.1.2

指針變量的定義與使用注意:*和&具有相同的優(yōu)先級(jí),結(jié)合方向是從右到左。

&*p即對(duì)*p取地址,等價(jià)于&a;

p等價(jià)于&a;*p等價(jià)于a。

3.指針變量的賦值(1)通過(guò)地址運(yùn)算符&進(jìn)行賦值(2)通過(guò)指針變量進(jìn)行賦值

例inti;int*p=&a;int*q=p;(3)給指針變量賦空值

例int*p=NULL;

例inta=5;int*p=&a;6.1.2

指針變量的定義與使用內(nèi)存5……2010……2010a201020302050pq

1.指針變量的算術(shù)運(yùn)算加減運(yùn)算:一個(gè)指針可以加、減一個(gè)整數(shù)n,其結(jié)果與指針?biāo)笇?duì)象的數(shù)據(jù)類型有

關(guān)。指針變量的值(地址)增加或減少“n×sizeof(指針類型)”

6.1.3

指針變量的運(yùn)算

例如,有下列定義:

int*p,a=2,b=3;假設(shè)a、b兩個(gè)變量被分配在一個(gè)連續(xù)的內(nèi)存區(qū),a的起始地址為1000。2

3…

2

3

……10002

3

…1004a(1000)b(1004)a(1000)b(1004)a(1000)b(1004)p=&ap+16.1.3

指針變量的運(yùn)算(1)指針的加減運(yùn)算常用于數(shù)組的處理。例如:inta[10],*p=a,*x;x=p+2;/*實(shí)際上是p加上2*4個(gè)字節(jié)賦給x,x指向數(shù)組的第三個(gè)分量*/(2)對(duì)于不同類型的指針,指針變量“加上”或“減去”一個(gè)整數(shù)n所移動(dòng)的字節(jié)數(shù)是不同的。例如:floata[10],*p=a,*x;p=p+2;/*實(shí)際上是p加上2*4個(gè)字節(jié)賦給x,x依然指向數(shù)組的第三個(gè)分量*/(3)*(p++)與(*p)++含義不同,前者表示地址自增,后者表示當(dāng)前所指向的變量自增。

2.指針變量的關(guān)系運(yùn)算

和基本類型變量一樣,指針能進(jìn)行關(guān)系運(yùn)算。例如:p>q,p<q,p==q,p!=q,p>=q等。6.1.3

指針變量的運(yùn)算

指針的關(guān)系運(yùn)算在指向數(shù)組的指針中廣泛的運(yùn)用,假設(shè)p、q是指向同一數(shù)組的兩個(gè)指針,執(zhí)行p>q的運(yùn)算,其含義為,若表達(dá)式結(jié)果為真(非0值),則說(shuō)明p所指元素在q所指元素之后。或者說(shuō)q所指元素離數(shù)組第一個(gè)元素更近些。

指針進(jìn)行關(guān)系運(yùn)算之前,指針必須初始化,另外,只有同類型的指針才能進(jìn)行比較。6.1.4

多級(jí)指針變量指針不但可以指向基本類型變量,亦可以指向指針變量,這種指向指針型數(shù)據(jù)的指針變量稱為指向指針的指針,或稱多級(jí)指針。二級(jí)指針的定義形式形式:

數(shù)據(jù)類型

**指針變量例如:

inta,*p,**pp;a=10;p=&a;pp=&p;2000pp(3000)1000p(2000)10a(1000)二級(jí)指針示意圖指針與數(shù)組6.26.2.1

指針與一維數(shù)組數(shù)組名是一個(gè)常量指針,它的值為該數(shù)組的首地址。指向數(shù)組的指針的定義方法與指向基本類型變量的指針的定義方法相同,例如:inta[5]={1,2,3,4,5};int*p;p=a;(把數(shù)組的首地址賦給指針變量p)6.2.1

指針與一維數(shù)組由于數(shù)組名代表數(shù)組首地址,是一個(gè)地址常量。因此,下面兩個(gè)語(yǔ)句等價(jià):

p=&a[0];p=a;在定義指針變量的同時(shí)可賦初值:

inta[10],*p=&a[0];(或int*p=a;)

等價(jià)于:

int*p;p=&a[0];12345pa[0]a[1]a[2]a[3]a[4]a數(shù)組指針示意圖6.2.1

指針與一維數(shù)組*(p+i)a數(shù)組a[0]a[1]a[2]a[i]a[9]pp+1,a+1p+i,a+ip+9,a+9綜上所述,引用一個(gè)數(shù)組元素有:(1)下標(biāo)法:如a[i]形式;(2)指針?lè)ǎ喝?(a+i)或*(p+i)。其中a是數(shù)組名,p是指向數(shù)組的指針變量,其初值p=a。

可以通過(guò)指針變量的運(yùn)算來(lái)訪問(wèn)數(shù)組的其他元素,如果p的初值為&a[0],則:p+i和a+i就是a[i]的地址,*(p+i)或*(a+i)是p+i或a+i所指向的數(shù)組元素,即a[i]。指向數(shù)組的指針變量也可以帶下標(biāo),如p[i]與*(p+i)、a[i]等價(jià)。6.2.1

指針與一維數(shù)組例6.4:用三種方法輸出數(shù)組全部元素。(1)下標(biāo)法voidmain(){ inta[10]; inti; for(i=0;i<10;i++) scanf("%d",&a[i]); printf("\n"); for(i=0;i<10;i++) printf("%d",a[i]);}6.2.1

指針與一維數(shù)組(2)通過(guò)數(shù)組名計(jì)算數(shù)組元素地址,輸出元素的值voidmain(){ inta[10]; inti; for(i=0;i<10;i++) scanf("%d",&a[i]); printf("\n"); for(i=0;i<10;i++) printf("%d",*(a+i));}6.2.1

指針與一維數(shù)組(3)用指針變量指向數(shù)組元素voidmain(){ inta[10]; int*p,i; for(i=0;i<10;i++) scanf("%d",&a[i]); printf("\n"); for(p=a;p<(a+10);p++) printf("%d",*p);}三種方法的比較:用下標(biāo)法比較直觀,能直接知道是第幾個(gè)元素;而使用指針?lè)▌t執(zhí)行效率更高6.2.1

指針與一維數(shù)組使用指針變量時(shí),應(yīng)注意:

(1)指針變量可實(shí)現(xiàn)使本身的值改變。

p++合法;但a++不合法(a是數(shù)組名,代表數(shù)組首地址,在程序運(yùn)行中是固定不變的。)(2)要注意指針變量的當(dāng)前值。voidmain(){inta[10];int*p,i;p=a;for(;p<a+10;p++)scanf("%d",p);printf("\n");for(;p<(a+10);p++)printf("%d",*p);}不能&p增加:p=a;6.2.1

指針與一維數(shù)組(3)*p++相當(dāng)于*(p++),因?yàn)?與++優(yōu)先級(jí)相同,且結(jié)合方向從右向左,其作用是先獲得p指向變量的值,然后執(zhí)行p=p+1;。(4)*(p++)與*(++p)意義不同,后者是先p=p+1,再獲得p指向的變量值。若p=a,則*(p++)是先輸出a[0],再讓p指向a[1];

*(++p)是先使p指向a[1],再輸出p所指的a[1](5)(*p)++表示的是將p指向的變量值+1。

1.二維數(shù)組的地址6.2.2

指針與二維數(shù)組a[0]a[1]aa+1inta[2][3];*a*(a+1)a、a+1都是指針,它們是長(zhǎng)度為3的整數(shù)數(shù)組a是一個(gè)長(zhǎng)度為2的數(shù)組數(shù)組元素是長(zhǎng)度為3的數(shù)組6.2.2

指針與二維數(shù)組對(duì)二維數(shù)組inta[2][3],有a——二維數(shù)組的首地址,即第0行的首地址a+i——第i行的首地址a[i]*(a+i)

——第i行第0列的元素地址a[i]+j*(a+i)+j

——第i行第j列的元素地址*(a[i]+j)*(*(a+i)+j)a[i][j]a+i=&a[i]=a[i]=*(a+i)=&a[i][0],值相等,含義不同a+i

&a[i],表示第i行首地址,指向行a[i]

*(a+i)

&a[i][0],表示第i行第0列元素地址,指向列inta[2][3];a[0]a[1]100010121000100410121016a[0][0]a[0][1]a[1][1]a[0][2]a[1][2]aa+1a[1][0]6.2.2

指針與二維數(shù)組inta[2][3];二維數(shù)組元素表示形式:(1)a[1][2](2)*(a[1]+2)(3)*(*(a+1)+2)地址表示:(1)a+1

(2)&a[1][0](3)a[1](4)*(a+1)行指針a[0][0]a[0][1]a[1][0]a[1][1]a[0][2]a[1][2]地址表示:(1)&a[1][2](2)a[1]+2(3)*(a+1)+2列指針

2.指向二維數(shù)組的指針變量6.2.2

指針與二維數(shù)組(1)指向數(shù)組元素的指針變量。這種變量的定義與普通指針變量定義相同,其類型與元素?cái)?shù)值類型相同。例如:int*p,a[2][3];

p=&a[1][2];(2)指向一維數(shù)組(二維數(shù)組的一行)的指針,也稱行指針。定義形式為:

類型標(biāo)識(shí)符(*指針變量名)[元素個(gè)數(shù)]例如:int(*p)[3];6.2.2

指針與二維數(shù)組(1)int(*p)[3];定義一個(gè)指針變量p,p指向包含3個(gè)元素的一維數(shù)組。(2)p+i與*(p+i)的區(qū)別:

p+i是指向第i行的指針(第i行的首地址);

*(p+i)是指向第i行第1個(gè)元素的地址;

兩者數(shù)值相等,但含義不同:p+i的增值將以行長(zhǎng)為單位,而*(p+i)增值將以元素長(zhǎng)度為單位。

注意:指針與字符串6.3

指向字符串的指針?lè)Q字符指針 定義形式:char*指針名6.3.1字符串指針利用指針來(lái)對(duì)字符串進(jìn)行操作:通過(guò)在定義時(shí)初始化指針變量使指針指向一個(gè)字符串。用指針變量實(shí)現(xiàn)對(duì)字符串的訪問(wèn)。charstr[]=”student”;

字符數(shù)組名同樣是字符數(shù)組的首地址,是常量指針,表示形式同一維數(shù)組。str[0]sstrstr[1]tstr+1str[2]ustr+2str[3]dstr+3str[4]estr+4str[5]nstr+5str[6]tstr+6str[7]\0str+7

(1)通過(guò)在定義時(shí)初始化指針變量使指針指向一個(gè)字符串。字符指針示例。例6.7#include<stdio.h>voidmain(){char*ch="student";printf("%s",ch);}6.3.1字符串指針chstudent\0(2)用指針變量來(lái)實(shí)現(xiàn)對(duì)字符串的訪問(wèn)。輸出字符串中n個(gè)字符后的所有字符。例6.8#include<stdio.h>voidmain(){char*ch="IloveChina!"; intn=7; ch=ch+n; printf("%s\n",ch);}6.3.1字符串指針運(yùn)行結(jié)果如下:

(1)字符指針變量本身是一個(gè)變量,定義后編譯系統(tǒng)為其分配一個(gè)用于存放地址的內(nèi)存單元,具體指向的內(nèi)存單元需要通過(guò)給指針變量賦值來(lái)確定。字符數(shù)組定義后,編譯系統(tǒng)會(huì)為其分配一段連續(xù)的內(nèi)存單元,首地址由數(shù)組名表示。

(2)字符指針可以整體賦值,字符數(shù)組只能一個(gè)一個(gè)元素單獨(dú)賦值。6.3.2

字符型指針與字符數(shù)組的區(qū)別例如;char*ch=”IloveChina!”;可以寫(xiě)成char*ch;ch=”IloveChina!”;//正確,ch是指針變量,字符串整體賦值可是,chara[20]=”IloveChina!”;不能寫(xiě)成chara[20];a=”IloveChina!”;//錯(cuò)誤,a代表首地址,只能存放一個(gè)字符,不能整體賦值指針與函數(shù)6.46.4.1

指針作為函數(shù)參數(shù)

函數(shù)形參為指針變量,實(shí)參為指針變量#include<stdio.h>voidswap(int*p,int*q){ inttemp; temp=*p; *p=*q; *q=temp;}

輸入兩個(gè)整數(shù),按從大到小的順序輸出。例6.96.4.1

指針作為函數(shù)參數(shù)運(yùn)行結(jié)果如下:輸入:35↙輸出:5,3voidmain(){inta,b; int*p1,*q1;printf("請(qǐng)輸入兩個(gè)整數(shù):"); scanf("%d%d",&a,&b); p1=&a; q1=&b; if(a<b) swap(p1,q1);//調(diào)用swap函數(shù)printf("按大小順序輸出:"); printf("%d

溫馨提示

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