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

下載本文檔

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

文檔簡介

第9章指針[Return]本章學(xué)習(xí)目標(biāo)

掌握指針和指針變量的概念掌握指針變量的定義及運(yùn)算掌握指針處理數(shù)組的方法掌握指針處理字符串的方法掌握函數(shù)指針的概念和含有指針參數(shù)的函數(shù)的定義及調(diào)用方法本章主要內(nèi)容9.1指針與內(nèi)存地址9.2變量的指針與指針變量9.3數(shù)組指針9.4字符串指針9.5函數(shù)指針9.6返回指針值的函數(shù)9.7指針數(shù)組和指向指針的指針9.1指針與內(nèi)存地址9.1.1變量的地址在定義一個(gè)變量時(shí),系統(tǒng)首先會(huì)在內(nèi)存中為這個(gè)變量分配一塊存儲(chǔ)區(qū)用來存放這個(gè)變量的值。而這塊存儲(chǔ)區(qū)的大小是由變量類型所決定的。例如,在C系統(tǒng)中一個(gè)int型數(shù)據(jù)占2個(gè)字節(jié),因此當(dāng)我們定義一個(gè)int型變量時(shí),系統(tǒng)就會(huì)為這個(gè)變量分配一個(gè)大小為2個(gè)字節(jié)的存儲(chǔ)區(qū)。為了方便管理這些存儲(chǔ)區(qū),操作系統(tǒng)會(huì)給內(nèi)存中的每一個(gè)字節(jié)進(jìn)行編號(hào),這個(gè)編號(hào)就叫做內(nèi)存的“地址”,而每一個(gè)變量所占據(jù)存儲(chǔ)區(qū)的第一個(gè)字節(jié)的編號(hào)稱為是該變量的“地址”

例如,我們定義三個(gè)整型變量:intm,n,k;定義時(shí),假設(shè)系統(tǒng)為這三個(gè)變量分配存儲(chǔ)空間的情況如圖9-1所示。由于int類型在C系統(tǒng)中占2個(gè)字節(jié),所以在定義m,n,k三個(gè)變量時(shí),系統(tǒng)將編號(hào)為1000和1001的兩個(gè)字節(jié)分配給m,將1002、1003兩個(gè)字節(jié)分配給n,將1004、1005兩個(gè)字節(jié)分配給k。因此變量m的地址就是1000,變量n的地址是1002,變量k的地址是1004。mnk……100010021004圖9-1系統(tǒng)分配地址……9.1.2變量在內(nèi)存中的存取1、變量在內(nèi)存中的存儲(chǔ)系統(tǒng)對(duì)變量值的存取實(shí)際都是通過地址進(jìn)行的。例如:m=20;n=25;k=30;程序在執(zhí)行這三條賦值語句時(shí),系統(tǒng)會(huì)根據(jù)變量名m、n、k的地址(1000、1002、1004)找到它們在內(nèi)存中所對(duì)應(yīng)的存儲(chǔ)區(qū),然后將數(shù)值20、25、30分別存放到這些存儲(chǔ)區(qū)中,從而完成了賦值操作。如圖9-2mnk……100010021004圖9-2賦值后的內(nèi)存情況……2025302、從變量中讀取數(shù)據(jù)從變量中讀取已存的數(shù)據(jù)也是通過地址進(jìn)行的。例如,程序在執(zhí)行printf(“%d”,m);時(shí),系統(tǒng)會(huì)根據(jù)變量名m找到它所對(duì)應(yīng)的地址1000,然后從編號(hào)為1000、1001的兩個(gè)字節(jié)的存儲(chǔ)區(qū)中取出所存放的數(shù)據(jù)20,然后將它輸出到控制臺(tái)中。由此可見,系統(tǒng)通過變量地址就可以方便地對(duì)變量單元進(jìn)行訪問(這種方式也稱為“直接訪問”方式),因此我們可以形象地說變量地址“指向”了該變量單元。在C語言中,也將地址叫做“指針”,變量的地址就稱為變量的“指針”。[Return]9.2 變量的指針與指針變量9.2.1什么是指針變量訪問某一變量單元還可以通過一種“間接訪問”的方式,可以先將某一變量的地址存放到另外一個(gè)特殊的變量中,然后通過訪問這個(gè)特殊變量中所存放的地址從而得到該地址所指向的變量單元中的值。例如:intm=3;假設(shè)系統(tǒng)為變量m分配的存儲(chǔ)空間的地址為2000,現(xiàn)定義一個(gè)特殊變量p,將變量m的地址(2000)存放到p中。如圖9-3所示。20003pm圖9-3變量p的存儲(chǔ)圖由于特殊變量p中存放的是m的地址2000,所以通過訪問p就可以間接得到m的值3。這樣就好象在特殊變量p和變量m之間建立了一種聯(lián)系,即通過p可以得到m的地址,從而得到m的值。這種聯(lián)系一般稱為“指向”,特殊變量p稱為“指針變量”,p和m的關(guān)系就可以稱為指針變量p指向變量m。指針變量:專門用來存放另一變量的地址(既指針)的變量?!⒁猓褐羔樧兞恐荒艽娣抛兞康牡刂罚戎羔槪?,而不能存放其他類型的數(shù)據(jù)。9.2.2指針變量的定義在使用指針變量前必須要先定義,指針變量的定義格式為:指針變量所指變量的類型

﹡指針變量名定義格式中“﹡”表示所定義的變量是一個(gè)指針變量,例如:int﹡p;表示p是一個(gè)指向整型變量的指針變量,既只能存放整型變量的地址,而不能存放其他類型的地址。如果一行定義多個(gè)指針變量,不同的指針變量名之間要用“,”隔開。例如:char﹡p1,﹡p2,﹡p3;※注意:c語言的使用者和一些資料經(jīng)常將定義指針變量簡化說成定義指針,實(shí)際指針和指針變量是兩個(gè)完全不同的概念:指針是指地址,是某種特定類型的數(shù)據(jù)在內(nèi)存中的存放地址;指針變量是指存放指針(既地址)的變量。因此,對(duì)于平時(shí)所說的“定義一個(gè)指針”就是指定義一個(gè)指針變量。9.2.3指針變量的引用對(duì)指針變量進(jìn)行賦值和引用主要通過“&”和“﹡”兩個(gè)運(yùn)算符實(shí)現(xiàn)的。1.“&”運(yùn)算符“&”運(yùn)算符又叫做取地址運(yùn)算符,它是單目運(yùn)算符,可以返回某一變量的內(nèi)存地址,常用于對(duì)指針變量進(jìn)行賦值的操作中。例如: intm; int﹡p; p=&m;

/*將變量m的地址獲取并賦給指針變量p,表示p指向變量m*/賦值后的示意圖如圖9-4所示。

&mpm圖9-4取變量m地址在對(duì)指針變量進(jìn)行賦值時(shí)應(yīng)該注意以下幾點(diǎn):(1)由于指針變量存放的是地址(指針),因此不能將其他非地址類型的數(shù)據(jù)賦給指針變量。例如以下的賦值不合法: int﹡p; p=100;/*錯(cuò)誤,不能將一個(gè)整型數(shù)據(jù)賦給指針變量*/(2)對(duì)指針變量進(jìn)行賦值時(shí),注意不要將“p=&m”寫成“﹡p=&m”。因?yàn)椤癌~p=&m”不是將m的地址賦給p,而是將m的地址賦給指針變量p所指的變量。(3)對(duì)指針變量進(jìn)行賦值時(shí),指針變量的數(shù)據(jù)類型應(yīng)該與指針變量中所要存放地址的變量的類型相同。例如,如果定義“char﹡q”,則q只能指向字符類型的變量,而不能指向其他類型的變量。例如: intn; char﹡q; q=&n;/*錯(cuò)誤,指針變量q只能存放字符類型變量的地址*/2.“﹡”運(yùn)算符“﹡”運(yùn)算符又叫做“間接訪問”或“取地址內(nèi)容”運(yùn)算符,該運(yùn)算符也是單目運(yùn)算符,它與指針變量結(jié)合,用來表示該指針變量所指變量的值。/*exam9-1*/#include“stdio.h”main(){intm;int﹡p;m=5;p=&m;/*將m的地址賦給p*/printf(“m=%d\n”,m);printf(“﹡p=%d\n”,﹡p);} /*

﹡p代表的就是p所指的變量單元m的值*/[演示]/*exam9-2*/#include“stdio.h”main(){intm;int﹡p;m=5;p=&m;/*將m的地址賦給p*/﹡p=10;

/*將10賦給p所指的變量單元*/printf(“m=%d\n”,m);printf(“﹡p=%d\n”,﹡p);} 本程序中,在將5賦給變量m后,雖然沒有直接改變m的值,但由于指針變量p指向m,因此程序第5行改變﹡p的值實(shí)際就是改變p所指變量m的值,即m的輸出結(jié)果為10。[演示]需要說明的是,當(dāng)一個(gè)指針變量沒有指向任何存儲(chǔ)空間時(shí)(即沒有對(duì)指針變量進(jìn)行賦值),不能使用“﹡”運(yùn)算符來進(jìn)行指針取內(nèi)容運(yùn)算。例如: #include“stdio.h” main() { int﹡p; printf(“%d”,﹡p);/*錯(cuò)誤,因?yàn)閜沒有指針任何存儲(chǔ)空間*/ } 在以上的程序中,由于指針變量p沒有指向任何的存儲(chǔ)空間,即﹡p并不存在,因此直接引用輸出﹡p是錯(cuò)誤的。但如果運(yùn)行以上的錯(cuò)誤程序,讀者會(huì)發(fā)現(xiàn)該程序不但可以正常運(yùn)行,而且輸出的結(jié)果會(huì)是一串?dāng)?shù)字。實(shí)際上這串?dāng)?shù)字結(jié)果是毫無意義的,它只是一個(gè)隨機(jī)數(shù),這是因?yàn)槲覀冸m然沒有給指針變量p進(jìn)行賦值,但C語言系統(tǒng)在進(jìn)行編譯的時(shí)候會(huì)隨機(jī)地賦給指針變量p一個(gè)地址值,因此輸出的這個(gè)數(shù)字結(jié)果是一個(gè)沒有任何意義的值。3.“&”和“﹡”的優(yōu)先級(jí)關(guān)系“&”和“﹡”的優(yōu)先級(jí)相同,它們與“++”是同一級(jí)別,僅次于“()”,因此當(dāng)它們在一起使用的時(shí)候,按自右而左的方向進(jìn)行結(jié)合運(yùn)算。例如,假設(shè)指針變量p已指向變量m(p=&m),則運(yùn)行&﹡p時(shí),先進(jìn)行﹡p的運(yùn)算,即變量m,然后再進(jìn)行&運(yùn)算。因此&﹡p運(yùn)算就等價(jià)于&m運(yùn)算,表達(dá)式返回的值就是變量m的地址。同樣,當(dāng)執(zhí)行﹡&m時(shí),先執(zhí)行&m,即返回變量m的地址,然后再進(jìn)行*運(yùn)算,最后表達(dá)式返回的值就是變量m的值。/*exam9-3*/#include“stdio.h”main(){intm;int﹡p;m=10;p=&m;printf(“m=%d,﹡p=%d,﹡&m=%d\n”,m,﹡p,﹡&m);printf(“&m=%x,p=%x,&﹡p=%x\n”,&m,p,&﹡p);} } [演示]m=10,*p=10,*&m=10&m=12ff7c,p=12ff7c,&*p=12ff7c程序運(yùn)行結(jié)果:﹡p和﹡&m的值就是變量m的值;p和&﹡p的值就是變量m的地址指針變量應(yīng)用舉例例9-4通過指針變量實(shí)現(xiàn)將兩個(gè)整型數(shù)按照從小到大的順序輸出/*exam9-4*/#include“stdio.h”main(){intm,n;int﹡p,﹡p1,﹡p2;scanf(“%d,%d”,&m,&n);/*從鍵盤輸入m和n的值*/p1=&m;p2=&n;if(m>n)p=p1;p1=p2;p2=p;/*交換指針變量p1、p2所指向的對(duì)象*/printf(“m=%d,n=%d\n”,m,n);printf(“﹡p1=%d,﹡p2=%d\n”,﹡p1,﹡p2);}[演示]15,10↙m=15,n=10*p1=10,*p2=15程序運(yùn)行結(jié)果:例9-4程序分析:本程序中,p1指向變量m,p2指向變量n。當(dāng)輸入m=15,n=10時(shí),由于m>n,所以執(zhí)行“p=p1;p1=p2;p2=p”,將指針變量p1與p2的值進(jìn)行交換。在這里請(qǐng)注意,p1與p2交換的只是它們所指向變量的地址(即交換完后p1指向變量n,p2指向變量m),而變量m與n的值卻沒有改變。因此在輸出﹡p1和﹡p2時(shí),實(shí)際輸出的是變量n和m的值。指針變量p1與p2交換過程如圖9-4所示。10&m&n15指針變量p1指針變量p2變量m變量np1與p2交換前(a)&m10&n15指針變量p1指針變量p2變量m變量np1與p2交換后(b)圖9-4指針變量p1與p2交換示意圖例9-4通過指針變量實(shí)現(xiàn)將兩個(gè)整型數(shù)按照從小到大的順序輸出/*exam9-4*/#include“stdio.h”main(){intm,n;int﹡p,﹡p1,﹡p2;scanf(“%d,%d”,&m,&n);

/*從鍵盤輸入m和n的值*/p1=&m;p2=&n;if(m>n)p=p1;p1=p2;p2=p;/*交換指針變量p1、p2所指向的對(duì)象*/printf(“m=%d,n=%d\n”,m,n);printf(“﹡p1=%d,﹡p2=%d\n”,﹡p1,﹡p2);}15,10↙m=10,n=15*p1=10,*p2=15程序運(yùn)行結(jié)果:對(duì)于指針變量p,當(dāng)直接引用p時(shí),代表的是p所指向變量的地址;當(dāng)引用﹡p時(shí),代表的是p所指向的變量的值。9.2.3指針變量的引用在第七章討論函數(shù)的調(diào)用方式時(shí),我們介紹了函數(shù)的參數(shù)可以是整型、實(shí)型、字符型等類型的數(shù)據(jù),這種函數(shù)的調(diào)用一般被稱為“傳值調(diào)用”。除了“傳值調(diào)用”的函數(shù)外,C語言還提供了一種調(diào)用函數(shù)的方式——“傳址調(diào)用”,這種函數(shù)的特點(diǎn)是參數(shù)的類型是指針類型?!皞髦嫡{(diào)用”的函數(shù)和“傳址調(diào)用”的函數(shù)在形式上和功能上有什么區(qū)別呢?我們先來看兩個(gè)例子。例9-6通過“傳值調(diào)用”的方式,實(shí)現(xiàn)交換兩個(gè)變量m、n的值/*exam9-6*/#include“stdio.h”voidswap(intx,inty){inttemp;temp=x;x=y;y=temp;}main(){intm,n;m=5;n=10;swap(m,n);/*將m,n的值作為實(shí)參傳遞給swap函數(shù)*/printf(“m=%d,n=%d\n”,m,n);}m=5,n=10程序運(yùn)行結(jié)果:[演示]程序分析:本程序的意圖是通過swap(intx,inty)函數(shù)實(shí)現(xiàn)對(duì)變量m和n進(jìn)行值交換,但是在輸出結(jié)果中m和n的值卻沒有改變。這是因?yàn)樵诤瘮?shù)調(diào)用時(shí),m的值傳給x,n的值傳給y。在執(zhí)行完“temp=x;x=y;y=temp;”后,互換的是x和y的值,main()函數(shù)中的m和n的值卻沒有互換。由此可見,“傳值調(diào)用”中的單向傳送的值傳遞方式并不能將形參值的改變傳遞給實(shí)參值。例9-6中的參數(shù)傳遞示意圖如圖9-5所示。551010mxnym、n的值傳遞給x、y(a)圖9-5“傳值調(diào)用”參數(shù)傳遞示意圖510執(zhí)行完swap函數(shù)后各變量的值(b)105mnxy因此,要想使被調(diào)函數(shù)中改變了的變量值能夠被主調(diào)函數(shù)所用,就不能采用“傳值調(diào)用”的函數(shù)方法,而應(yīng)該將指針變量作為函數(shù)參數(shù),即在函數(shù)的調(diào)用過程中將變量的地址作為實(shí)參值傳遞給函數(shù),這樣如果在函數(shù)執(zhí)行過程中指針變量所指向的變量值發(fā)生了變化,那么當(dāng)函數(shù)調(diào)用完畢后,主調(diào)函數(shù)的這些變量值的變化仍舊保留下來,這樣就實(shí)現(xiàn)了通過被調(diào)函數(shù)修改主調(diào)函數(shù)中變量的值。這種采用指針變量作為形參的函數(shù)調(diào)用方法也稱為“傳址調(diào)用”。例9-7通過“傳址調(diào)用”的方式,實(shí)現(xiàn)交換兩個(gè)變量m、n的值/*exam9-7*/#include“stdio.h”voidswap(int﹡p,int﹡q)/*swap函數(shù)功能是交換指針變量p,q所指變量的值*/{inttemp;temp=﹡p;﹡p=﹡q;﹡q=temp;}main(){intm,n;int﹡p1,﹡p2;m=5;n=10;p1=&m;/*指針變量pointer_1指向變量m*/p2=&n;/*指針變量pointer_1指向變量n*/swap(p1,p2);/*將m,n的地址作為實(shí)參傳遞給swap函數(shù)*/printf(“m=%d,n=%d\n”,m,n);}[演示]程序分析:main函數(shù)中定義了兩個(gè)整型變量m和n,定義了兩個(gè)整型指針變量p1和p2。p1指向變量m,p2指向變量n,如圖9-6(a)所示。p1,p2做為實(shí)參將它們所存放的m和n的地址傳遞給swap函數(shù)的參數(shù)p和q(此時(shí)p和q存放的是變量m和n的地址),如圖9-6(b)所示。當(dāng)swap函數(shù)中的“temp=*p;*p=*q;*q=temp”執(zhí)行后,進(jìn)行交換的是p和q所指向的變量的值,即變量m和n的值進(jìn)行互換,如圖9-6(c)所示。&n&m5&n10p1mp2n(a)圖9-6指針變量做參數(shù)實(shí)現(xiàn)交換m和n的值&m5p1m&mp10p2n&n(b)&m10&n5p1mp2n(c)q因此,如果想通過被調(diào)函數(shù)來改變主調(diào)函數(shù)中變量的值,可以:(1)如果主調(diào)函數(shù)需要改變n個(gè)變量的值,那么在被調(diào)用函數(shù)中就相應(yīng)地定義n個(gè)指針形參。(2)在主調(diào)函數(shù)調(diào)用被調(diào)函數(shù)時(shí),主調(diào)函數(shù)將需要改變值的n個(gè)變量的地址作為實(shí)參傳給被調(diào)用函數(shù)。(3)被調(diào)函數(shù)執(zhí)行時(shí),通過修改被調(diào)函數(shù)的指針形參的值從而改變主調(diào)函數(shù)中相應(yīng)變量的值。例9-8輸入三個(gè)整數(shù),然后找出并輸出最小的整數(shù)/*exam9-8*/#include“stdio.h”voidgetMin(int﹡pt1,int﹡pt2,int﹡pt3,int﹡pt){﹡pt=﹡pt1;if(﹡pt>﹡pt2) ﹡pt=﹡pt2;elseif(﹡pt>﹡pt3) ﹡pt=﹡pt3;}main(){inta,b,c,min;int﹡p1,﹡p2,﹡p3,﹡p;scanf(“%d%d%d”,&a,&b,&c);/*輸入三個(gè)整數(shù)*/p1=&a;p2=&b;p3=&c;p=&min;getMin(p1,p2,p3,p);/*調(diào)用getMin函數(shù)找出最小整數(shù)*/printf(“最小整數(shù)為:%d”,min);/*輸出最小整數(shù)min的值*/}[演示][Return]9.3 數(shù)組指針我們知道數(shù)組是由若干個(gè)數(shù)組元素組成的,而每個(gè)數(shù)組元素在內(nèi)存中又有相應(yīng)的地址,因此指針變量除了可以指向一般的變量外,也可以指向數(shù)組或數(shù)組元素。指針與數(shù)組有著密切的聯(lián)系,使用指針的移動(dòng)不但可以方便地訪問數(shù)組元素還可以使程序在運(yùn)行效率上有著顯著地提高。9.3.1指向數(shù)組元素的指針指向數(shù)組元素指針的方法與指向普通變量指針的方法相同。例如: inta[5]; int﹡p; p=&a[0];該程序中定義了一個(gè)整型數(shù)組a和整型指針變量p,將數(shù)組元素a[0]

的地址賦給指針變量p,p就指向了數(shù)組a的第一個(gè)元素。如圖9-7所示。a[0]a[1]a[2]a[3]a[4]&a[0]p圖9-7指向一維數(shù)組的指針變量※注意:指針變量的類型必須要和數(shù)組類型一致,即如果數(shù)組為int類型,則指針變量也必須為int類型。在C語言中,同時(shí)規(guī)定數(shù)組名在使用時(shí)代表數(shù)組首元素的地址,因此p=&a[0]等價(jià)于p=a,即p指向數(shù)組第一個(gè)元素。和普通的指針變量一樣,在定義指向數(shù)組元素的指針變量的同時(shí)也可以對(duì)它賦初值。例如例9-9中的程序就等價(jià)于: inta[5]; int﹡p=&a[0];※注意:千萬不要把“p=a”認(rèn)為是p指向a整個(gè)數(shù)組,在這里只是將數(shù)組a的首元素地址賦給了p。9.3.2通過指針引用數(shù)組元素引用數(shù)組中的元素除了可以使用常見的下標(biāo)法之外,還可以使用指針法。在C語言中規(guī)定,如果指針變量p指向數(shù)組中的某一個(gè)元素,則p+1就指向該數(shù)組的下一個(gè)元素。例如,如果指針變量p指向數(shù)組a的第一個(gè)元素a[0],則p+1就指向下一個(gè)元素a[1],p+2指向數(shù)組元素a[2]。依次類推,p+i就指向數(shù)組元素a[i]。因此我們可以得出:(1)&a[i],p+i,a+i均表示a數(shù)組的第i個(gè)元素的地址。注意,這里的p+i不是將p的值簡單地加i,而是在p所指元素的地址上加上i個(gè)數(shù)組元素所占的字節(jié)數(shù)。例如,假設(shè)數(shù)組a是一個(gè)整型數(shù)組,則p+i所代表的地址就為p+i*2(2為一個(gè)整型元素所占的字節(jié)數(shù)),即p+i指向數(shù)組的第i個(gè)元素a[i]。(2)a[i],﹡(p+i),﹡(a+i)均表示a數(shù)組的第i個(gè)元素的值。由于p+i,a+i均表示a[i]元素的地址,因此﹡(p+i),﹡(a+i)就代表的是元素a[i]的值。這種引用數(shù)組元素的方法一般也稱為指針法。例9-10分別使用下標(biāo)法和指針法輸出數(shù)組中各元素的值/*exam9-10*/#include“stdio.h”main(){inta[10];inti,﹡p;for(i=0;i<10;i++)scanf(“%d”,&a[i]);printf(“\n”);for(i=0;i<10;i++)printf(“%d”,a[i]);/*利用數(shù)組下標(biāo)法輸出數(shù)組中的元素*/printf(“\n”);for(i=0;i<10;i++)printf(“%d”,﹡(a+i));/*利用指針法輸出10個(gè)元素的值,﹡(a+i)等價(jià)于a[i]*/printf(“\n”);for(p=a;p<(a+10);p++)printf(“%d”,﹡p);/*利用指針法輸出10個(gè)元素的值,通過指針變量p的移動(dòng)*//*來依次輸出數(shù)組中的10個(gè)元素*/} [演示]在此需要注意的是:(1)使用下標(biāo)法和使用﹡(a+i)的執(zhí)行效率是相同的,因?yàn)楫?dāng)使用下標(biāo)法訪問數(shù)組元素時(shí),C語言的編譯系統(tǒng)會(huì)將a[i]自動(dòng)轉(zhuǎn)換為﹡(a+i)進(jìn)行處理,即每次都需要計(jì)算元素地址,因此在執(zhí)行起來比較費(fèi)時(shí)。而使用指針變量直接指向數(shù)組元素,然后通過p++的移動(dòng)來訪問各元素的方法則不需要計(jì)算地址,因此執(zhí)行效率大大提高。(2)當(dāng)通過指針法來訪問數(shù)組元素時(shí),注意不能使用a++來移動(dòng)指針變量,因?yàn)閍是數(shù)組名,它代表數(shù)組的首地址,是一個(gè)常量,因此無法實(shí)現(xiàn)自加操作。例9-11使用指針法輸出數(shù)組中各元素的值/*exam9-11*/#include“stdio.h”main(){inta[10];inti,﹡p;for(p=a;p<(a+10);p++)scanf(“%d”,p);printf(“\n”);for(i=0;i<10;i++,p++)printf(“%d”,﹡p);}[演示]從程序運(yùn)行結(jié)果可以發(fā)現(xiàn)最后輸出的并不是我們期望的數(shù)組a的10個(gè)元素的值,而是毫無意義的一組數(shù)字。這是因?yàn)楫?dāng)程序執(zhí)行完第一個(gè)for循環(huán)后,指針變量p指向的是數(shù)組a的最后一個(gè)元素a[9],而并非是第一個(gè)元素a[0]。因此在執(zhí)行第二個(gè)for循環(huán)的時(shí)候,p++的值就超出了數(shù)組的范圍,從而使指針變量p指向了一組不可預(yù)料的存儲(chǔ)單元,導(dǎo)致最后輸出結(jié)果是一組毫無意義的數(shù)字。要解決這個(gè)問題,我們只需要在程序執(zhí)行完第一個(gè)for循環(huán)后,再讓p指向數(shù)組a的第一個(gè)元素就可以了。見程序9-12。例9-12/*exam9-12*/#include“stdio.h”main(){inta[10];inti,﹡p;for(p=a;p<(a+10);p++)scanf(“%d”,p);

p=a;/*令指針變量p指向數(shù)組a的一個(gè)元素*/for(i=0;i<10;i++,p++)printf(“%d”,﹡p);}[演示]9.3.3數(shù)組名作函數(shù)參數(shù)我們在第7章“函數(shù)的調(diào)用”時(shí)曾討論過,當(dāng)使用數(shù)組名作函數(shù)的參數(shù)時(shí),如果形參數(shù)組元素的值發(fā)生變化,實(shí)參數(shù)組元素的值也會(huì)隨之變化。例如:例9-13利用數(shù)組名作函數(shù)參數(shù)實(shí)現(xiàn)對(duì)10個(gè)整數(shù)進(jìn)行排序/*exam9-13*/#include“stdio.h”voidsort(intarray[]){ inti,j;intt,k;for(i=0;i<9;i++){k=i;for(j=i+1;j<10;j++){if(array[j]<array[k])k=j;} t=array[k];array[k]=array[i];array[i]=t;}}

main(){inta[10];inti;printf(“pleaseinput10numbers:\n”);for(i=0;i<10;i++)scanf(“%d”,&a[i]);printf(“\n”);sort(a);/*將數(shù)組名a作為實(shí)參傳給函數(shù)sort進(jìn)行排序*/printf(“thearrayhasbeensorted:\n”);for(i=0;i<10;i++)/*輸出排序后的數(shù)組a中的各元素*/printf(“%d”,a[i]);}pleaseinput10numbers:9876543210↙thearrayhasbeensorted:0123456789程序運(yùn)行結(jié)果:程序分析:之所以實(shí)參數(shù)組a的各元素值會(huì)隨著形參數(shù)組array各元素值的改變而改變,主要是因?yàn)閿?shù)組名代表的是數(shù)組的首地址,因此如果使用數(shù)組名作為實(shí)參,在調(diào)用函數(shù)時(shí)就會(huì)把數(shù)組的首地址傳給形參,這樣形參數(shù)組array和實(shí)參數(shù)組a就會(huì)共享同一段內(nèi)存空間,所以當(dāng)數(shù)組array中的元素值發(fā)生改變時(shí),數(shù)組a中的各元素值也會(huì)隨之改變。如果想通過函數(shù)調(diào)用來改變實(shí)參數(shù)組中的元素值,除了可以使形參和實(shí)參都采用數(shù)組名之外,還可以使用以下三種方法:1、函數(shù)實(shí)參用數(shù)組名,形參用指針變量2、函數(shù)實(shí)參用指針變量,形參用數(shù)組3、函數(shù)實(shí)參、形參均用指針變量[演示][演示][演示]9.3.4二維數(shù)組的指針和指向二維數(shù)組的指針變量1、二維數(shù)組的指針二維數(shù)組的指針(地址)相比一維數(shù)組的指針有著很大的不同。在C語言中,系統(tǒng)是將二維數(shù)組當(dāng)作一種特殊的一維數(shù)組來進(jìn)行處理的。例如: inta[2][3]={{1,2,3},{4,5,6}};這是一個(gè)兩行三列的二維數(shù)組,C語言將該數(shù)組的每一行看作是一個(gè)一維數(shù)組,用數(shù)組名a[0]、a[1]來表示。這兩個(gè)一維數(shù)組分別又含有三個(gè)元素(每一行的三個(gè)列元素),即第一行數(shù)組a[0]含有:a[0][0]、a[0][1]、a[0][2];第二行數(shù)組a[1]含有:a[1][0]、a[1][1]、a[1][2]。這樣這兩行一維數(shù)組就構(gòu)成了一個(gè)二維數(shù)組。如圖9-10所示?!⒁猓哼@里的a[0]、a[1]并不是實(shí)際存在的數(shù)組元素,它們代表的是每一行的數(shù)組名,而C語言又規(guī)定數(shù)組名代表數(shù)組首元素的地址,因此a[0]、a[1]分別代表第0行和第1行數(shù)組元素的首地址,即&a[0][0]和&a[0][1]除了可以使用每一行的一維數(shù)組名來代表該行的首地址之外,還可以使用二維數(shù)組名加下標(biāo)的方法來表示各行元素的首地址。例如,二維數(shù)組名a代表第0行元素的首地址,那么a+1就代表第1行元素的首地址,a+2代表第2行元素的首地址,a+n代表第n行元素的首地址。同時(shí),C語言又規(guī)定二維數(shù)組的行數(shù)組名a[0]與﹡(a+0)等價(jià),a[1]與﹡(a+1)等價(jià),因此二維數(shù)組的第i行元素的首地址還可以用﹡(a+i)來表示?!⒁猓河捎赼+i本身只是一個(gè)地址而不是一個(gè)實(shí)際的指針變量,所以﹡(a+i)并不代表指向a+i單元的值。請(qǐng)牢記,這里的﹡(a+i)只與一維數(shù)組名a[i]等價(jià),只代表二維數(shù)組a的第i行元素的首地址。下面我們討論如何表示每行數(shù)組中各列元素的地址。以二維數(shù)組a為例,由于已知第0行元素的首地址為a[0],因此可以用a[0]+1表示第0行第1列元素的地址,對(duì)于第i行第j列元素的地址,可以用a[i]+j進(jìn)行表示。又因?yàn)榈趇行數(shù)組元素的首地址a[i]與﹡(a+i)等價(jià),所以第i行第j列元素的地址也可以用﹡(a+i)+j表示。表9-1顯示了二維數(shù)組各元素的地址、值的表示形式。例9-17采用不同的地址計(jì)算方法輸出二維數(shù)組元素/*exam9-17*/#include“stdio.h”main(){inti,j;inta[2][3]={{1,2,3},{4,5,6}};for(i=0;i<2;i++){ for(j=0;j<3;j++){ printf(“%d”,a[i][j]);//使用數(shù)組下標(biāo)法輸出數(shù)組元素printf(“%d”,﹡(a[i]+j));//使用地址法輸出數(shù)組元素 printf(“%d”,﹡(﹡(a+i)+j));//使用地址法輸出數(shù)組元素} printf(“\n”);}}[演示]2、指向二維數(shù)組的指針變量使用指向二維數(shù)組的指針變量既可以順序訪問二維數(shù)組的元素值也可以訪問某個(gè)指定二維數(shù)組的元素值。(1)使用指針變量順序訪問二維數(shù)組的元素值。先看一個(gè)例子:例9-18使用指針變量順序輸出二維數(shù)組元素/*exam9-18*/#include“stdio.h”main(){inta[2][3]={{1,2,3},{4,5,6}};int﹡p;for(p=a[0];p<a[0]+6;p++) printf(“%d”,﹡p);}123456程序運(yùn)行結(jié)果為:在上例中,指針變量p首先指向二維數(shù)組a的第0行0列元素,然后通過p++使指針變量依次移動(dòng)到下一個(gè)元素,從而實(shí)現(xiàn)對(duì)二維數(shù)組所有元素的順序訪問。(2)使用指針變量訪問某個(gè)指定的二維數(shù)組元素程序例9-18的方法雖然可以順序訪問二維數(shù)組的元素,但無法訪問某個(gè)指定的元素(例如a[2][1])。為了解決這個(gè)問題,C語言提供了一種可以指向一維數(shù)組的指針變量(二維數(shù)組就是由若干行一維數(shù)組構(gòu)成的),使用這種指針變量可以方便地訪問二維數(shù)組中的任意一個(gè)元素,該指針變量也稱為二維數(shù)組的行指針變量。以下是行指針變量的定義形式:類型(﹡指針變量名)[n]說明:(1)()不能省略,如果省略了,指針變量就不再指向一維數(shù)組,而變成了一個(gè)指針數(shù)組。(2)n代表指向的一維數(shù)組所包含的元素?cái)?shù)。例如,int(﹡p)[4]代表指針變量p指向一個(gè)含有4個(gè)元素的一維數(shù)組。(3)假設(shè)一個(gè)行指針變量p指向一個(gè)二維數(shù)組a,那么可以使用﹡(﹡(p+i)+j)來訪問a的第i行第j列元素。(因?yàn)閜指向a的第0行,﹡(p+i)就代表a的第i行數(shù)組的首地址,﹡(p+i)+j代表a的第i行第j列元素的地址,因此﹡(﹡(p+i)+j)就代表數(shù)組a的第i行第j列元素的值。)例9-19使用行指針變量輸出二維數(shù)組的任意元素/*exam9-19*/#include“stdio.h”main(){inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};inti,j;int(﹡)p[4];scanf(“%d,%d”,&i,&j);//輸入要輸出的元素所在的行數(shù)和列數(shù)

p=a;

//p指向數(shù)組a的第0行printf(“a[%d][%d]=%d”,i,j,﹡(﹡(p+i)+j));//輸出第i行第j列元素的值}2,3↙a[2][3]=12程序運(yùn)行結(jié)果為:[Return]9.4 字符串指針9.4.1字符串的指針表示和引用 6.3節(jié)介紹過,一個(gè)非空的一維字符數(shù)組實(shí)際上是一個(gè)字符串,因此我們可以定義一個(gè)字符型的指針變量指向該字符數(shù)組,從而可以通過該指針變量對(duì)字符串進(jìn)行引用。例如:

例9-20利用指針變量輸出字符數(shù)組的內(nèi)容/*exam9-20*/#include“stdio.h”main(){charstring[]=“Iamaboy”;char﹡str;str=string;/*指針變量str指向字符數(shù)組的首元素*/for(;﹡str!=’\0’;str++)/*逐個(gè)輸出字符數(shù)組中的各個(gè)字符*/ printf(“%c”,﹡str);str=string;/*指針變量str指向string的首地址*/printf(“\n”);printf(“%s”,str);/*將字符數(shù)組內(nèi)容一次性輸出*/}IamaboyIamaboy程序運(yùn)行結(jié)果為:從例9-20可以看出,當(dāng)指針變量str指向字符數(shù)組string時(shí)(見圖9-11),若要輸出字符數(shù)組的內(nèi)容可以采用兩種方法:一種是通過指針變量的移動(dòng)逐個(gè)輸出字符數(shù)組的各字符;另一種方法是使用格式控制符“%s”將字符串內(nèi)容一次性輸出。

※注意:(1)如要逐個(gè)輸出字符串中的字符時(shí),printf函數(shù)的格式控制符使用“%c”。(2)如要一次性輸出整個(gè)字符串時(shí),printf函數(shù)的格式控制符使用“%s”,輸出項(xiàng)使用指針變量名。(實(shí)際上系統(tǒng)首先輸出指針變量所指向的字符,然后使指針變量逐步后移,依次輸出剩余的字符,直至遇到字符串的結(jié)束標(biāo)志’\0’為止)。(3)字符串在輸出時(shí),不包括結(jié)束字符’\0’。

字符型指針變量除了可以指向一維字符數(shù)組外,還可以直接指向一個(gè)字符串。例如:

char﹡str=”Iamaboy”; printf(“%s”,str);程序輸出的結(jié)果是”Iamaboy”。在這里雖然沒有定義字符數(shù)組,但C語言實(shí)際在內(nèi)存中就是使用字符數(shù)組來存放字符串的,因此: char﹡str=”Iamaboy”;等價(jià)于:char﹡str;str=”Iamaboy”;該程序是將”Iamaboy”的首地址賦給指針變量str,然后通過格式控制符”%s”將字符串的內(nèi)容一次性輸出?!⒁猓河捎赼+i本身只是一個(gè)地址而不是一個(gè)實(shí)際的指針變量,所以﹡(a+i)并不代表指向a+i單元的值。請(qǐng)牢記,這里的﹡(a+i)只與一維數(shù)組名a[i]等價(jià),只代表二維數(shù)組a的第i行元素的首地址。例9-21利用指針變量將字符串中的大寫字母轉(zhuǎn)換成小寫字母/*exam9-21*/#include“stdio.h”main(){charstring[];char﹡str;scanf(“%s”,string);/*輸入字符串內(nèi)容*/str=string;for(;﹡str!=’\0’;str++)/*逐個(gè)輸出字符數(shù)組中的各個(gè)字符*/{if(﹡str>=’A’&&﹡str<=’Z’)﹡str=﹡str+32;/*將字符串中的大寫字母轉(zhuǎn)換為小寫字母*/}str=string;/*指針變量str重新指向string的首地址*/printf(“%s”,str);}aBcDEF↙abcdef程序運(yùn)行結(jié)果為:9.4.2字符串指針作函數(shù)參數(shù)

和其他指針一樣,字符串指針也可以作為函數(shù)參數(shù),可以通過地址傳遞的方法將字符串從一個(gè)函數(shù)傳遞到另一個(gè)函數(shù)。在函數(shù)的調(diào)用過程中如果被調(diào)函數(shù)改變了字符串的內(nèi)容,那么主調(diào)函數(shù)中字符串內(nèi)容也會(huì)相應(yīng)發(fā)生改變。如果函數(shù)形參為字符指針變量,那么主調(diào)函數(shù)可以使用數(shù)組名或指針變量名作為函數(shù)的實(shí)參:(1)函數(shù)形參使用指針變量,實(shí)參使用一維數(shù)組名。(2)函數(shù)形參實(shí)參均使用字符指針變量。[例9-22演示][例9-23演示][Return]9.5函數(shù)指針9.5.1指向函數(shù)的指針變量

由于函數(shù)本身也有地址,所以指針變量除了可以指向變量、字符串和數(shù)組外,還可以指向函數(shù)。函數(shù)是一組指令的集合,系統(tǒng)在編譯函數(shù)時(shí)會(huì)將這些指令裝入內(nèi)存,C語言規(guī)定這些指令的首地址稱為函數(shù)的入口地址,也稱為函數(shù)的指針。因此,可以定義一個(gè)指針變量來存放某一個(gè)函數(shù)的指針,從而達(dá)到間接調(diào)用該函數(shù)的目的,這種指針變量也稱為指向函數(shù)的指針變量。定義形式為:數(shù)據(jù)類型(﹡變量名)(參數(shù)類型列表)說明:(1)“數(shù)據(jù)類型”指的是指針變量所指函數(shù)的返回值類型。(2)(﹡變量名)的()不能省略。例如:(﹡p)()不能寫成﹡p(),﹡p()代表的是一個(gè)返回指針類型的函數(shù)。(3)參數(shù)類型列表指的是定義指針變量時(shí),指針變量的參數(shù)類型表必須和所指函數(shù)的形參列表一致,即形參的個(gè)數(shù)相同、類型相同。例如,有函數(shù)intfunction(inta,intb),在定義指向該函數(shù)的指針變量時(shí),應(yīng)當(dāng)定義為:int(﹡p)(int,int)。(4)C語言規(guī)定函數(shù)名就代表函數(shù)的入口地址,因此給函數(shù)指針變量賦值時(shí),只要將函數(shù)名賦給指針變量就可以了,而不必給出函數(shù)的參數(shù)。例如:intfuction(inta,intb){………}main(){int(﹡p)(int,int);/*定義指向函數(shù)的指針變量*/

p=function;

/*指針變量p指向函數(shù)function*/}9.5.2用函數(shù)指針變量調(diào)用函數(shù)當(dāng)一個(gè)函數(shù)指針變量指向一個(gè)函數(shù)后,就可以使用這個(gè)指針變量來間接調(diào)用函數(shù)。下面先看一個(gè)普通函數(shù)調(diào)用的例子。

例9-25編寫函數(shù)求兩個(gè)整型數(shù)的和/*exam9-25*/#include“stdio.h”intadd(inta,intb){intc;c=a+b;return(c);}main(){intx,y,z;scanf(“%d,%d”,&x,&y);/*輸入兩個(gè)整數(shù)*/z=add(x,y);printf(“%d+%d=%d”,x,y,z);}本程序中,通過將x,y的值作為實(shí)參傳遞給add函數(shù),從而完成對(duì)add函數(shù)的調(diào)用,這也是一般調(diào)用函數(shù)的方法。如果使用函數(shù)指針變量調(diào)用add函數(shù),只需在函數(shù)調(diào)用時(shí)將函數(shù)名add改為(﹡變量名)即可。例如,將main函數(shù)改為: int(﹡p)(int,int); p=add;

z=(﹡p)(x,y);因此,使用指針變量調(diào)用函數(shù)時(shí),除了使用(﹡變量名)代替函數(shù)名外,還應(yīng)該根據(jù)需要加上函數(shù)的實(shí)參。另外需要注意的是,由于函數(shù)指針變量只能指向函數(shù)的入口地址而不能指向其他的任何地方,因此在使用函數(shù)指針變量時(shí),不能夠做類似于p++或p--的操作。例9-26使用函數(shù)指針變量調(diào)用函數(shù)找出任意兩個(gè)數(shù)中的小數(shù)/*exam9-26*/#include“stdio.h”intmin(intm,intn){ints;if(m<n)s=m;elses=n;return(s);}main(){inta,b,c;int(﹡p)(int,int);printf(“Inputthenumber:\n”);scanf(“%d,%d”,&a,&b);p=min;c=(﹡p)(a,b);printf(“Theminimumnumberis:\n%d”,c);}Inputthenumber:9,6↙Theminimumnumberis:6程序運(yùn)行結(jié)果:9.5.3用指向函數(shù)的指針作函數(shù)參數(shù) 指向函數(shù)的指針最常見的用途就是將該指針作為函數(shù)的參數(shù)傳遞給被調(diào)函數(shù),通過函數(shù)地址值的傳遞,實(shí)現(xiàn)被調(diào)函數(shù)可以根據(jù)不同的情況來調(diào)用不同的函數(shù),從而增強(qiáng)程序的靈活性。其一般的使用方法為:假設(shè)有兩個(gè)普通函數(shù):intfun1(intx1,inty1)、intfun2(intx2),現(xiàn)定義一個(gè)形參為函數(shù)指針的函數(shù)來完成對(duì)fun1和fun2的調(diào)用。例如:

intfun1(intx1,inty1){ ……}intfun2(intx2){ ……}fun(int(﹡p1)(int,int),int(﹡p2)(int)){ inta,b;

a=(﹡p1)(5,6);

}main(){

fun(fun1,fun2);}在main()函數(shù)中,程序?qū)⒑瘮?shù)fun1和fun2的入口地址傳給了函數(shù)fun的兩個(gè)參數(shù)p1和p2,這樣p1、p2就分別指向了函數(shù)fun1和fun2(見圖9-13),這也意味著就可以使用函數(shù)指針p1和p2間接訪問函數(shù)fun1和fun2了。在這里需要注意的是,如果main函數(shù)放在了函數(shù)fun1和fun2的上面,那么在main函數(shù)調(diào)用fun(fun1,fun2)之前需要對(duì)實(shí)參函數(shù)fun1和fun2進(jìn)行聲明,即:

main() { intfun1(int,int); intfun2(int); fun(fun1,fun2); }因此,由上可以看出使用含有函數(shù)指針參數(shù)的函數(shù)最大的好處就是可以靈活地調(diào)用函數(shù),特別是當(dāng)經(jīng)常調(diào)用的函數(shù)是不固定的時(shí)候。例如,假設(shè)程序第一次需要調(diào)用fun1和fun2函數(shù),第二次需要調(diào)用fun3和fun4函數(shù),這時(shí)如果使用傳統(tǒng)的直接調(diào)用函數(shù)的方法就會(huì)需要每次都得修改fun函數(shù),這樣就顯得十分繁瑣。但是如果使用函數(shù)指針變量來調(diào)用這些函數(shù),那么每次只要賦給fun函數(shù)不同的實(shí)參值就可以了,而不必修改fun函數(shù)本身。[Return]9.6 返回指針值的函數(shù)函數(shù)的返回值可以有多種類型,除了此前學(xué)習(xí)的整型、實(shí)型和字符型以外,函數(shù)還可以返回指針型數(shù)據(jù),即返回的數(shù)據(jù)是一個(gè)地址。返回值為指針類型的函數(shù)的定義形式一般如下:

類型﹡函數(shù)名(形參列表)

{

…… }說明:(1)類型指的是返回的指針指向的是什么類型的數(shù)據(jù)。(2)函數(shù)名前的﹡代表的是該函數(shù)返回值是一個(gè)指針數(shù)據(jù),即調(diào)用該函數(shù)的程序可以得到一個(gè)地址。例如: int﹡fun(inta) {

…… }代表定義了一個(gè)函數(shù),該函數(shù)的返回值是一個(gè)指向整型數(shù)據(jù)的地址。

[例9-28]根據(jù)例9-28可以看出,main函數(shù)在調(diào)用fun函數(shù)的時(shí)候,首先將字符串string的首地址賦給fun函數(shù)的形參﹡str,然后通過對(duì)str的操作將字符串中的大寫字母轉(zhuǎn)換成小寫字母,最后將轉(zhuǎn)換好的字符串首地址返回給主調(diào)函數(shù)main,因此最后輸出的s所指的數(shù)據(jù)就是已經(jīng)轉(zhuǎn)換好的字符串string?!舅伎肌吭趂un函數(shù)中是否有必要定義指向形參str的字符型指針變量p?[例9-29]※注意:函數(shù)返回的指針不能指向函數(shù)返回后便不存在的變量。例如: int﹡f(inta) { return&a; }這個(gè)函數(shù)返回的結(jié)果是非法的,主要因?yàn)樽兞縜為形參變量,該變量的生存周期是函數(shù)f的運(yùn)行階段,即當(dāng)f執(zhí)行完后,形參變量a也會(huì)隨之被釋放,因此主調(diào)函數(shù)所獲得的返回值是不可靠的。9.7 指針數(shù)組和指向指針的指針9.7.1指針數(shù)組 普通數(shù)組元素除了可以存儲(chǔ)整型、實(shí)型和字符型數(shù)據(jù)外,還可以存放指針型數(shù)據(jù)。如果某種數(shù)組存放的所有元素都是指向同一類型的指針變量,則稱該數(shù)組為指針數(shù)組。指針數(shù)組的一般定義形式為:

類型標(biāo)識(shí)符﹡數(shù)組名[長度]例如:

int﹡p[3];該語句定義了一個(gè)長度為3的指針數(shù)組,每個(gè)指針元素都可以指向整型變量。除此之外,C語言還允許在定義指針數(shù)組的同時(shí)就可以完成對(duì)數(shù)組的初始化操作。例如:

char﹡str[3]={“cat”,“dog”,“pig”};該語句定義了指針數(shù)組str,并且數(shù)組的3個(gè)元素分別指向3個(gè)字符串常量,即str的三個(gè)元素分別存放了三個(gè)字符串(字符串在內(nèi)存中的存儲(chǔ)形式是一維字符數(shù)組)的首地址。如圖9-14?!⒁猓涸诙x指針數(shù)組時(shí),一定不能將int﹡p[3]寫成int(﹡p)[3],因?yàn)閕nt(﹡p)[3]代表的是指向一維數(shù)組的指針變量。

指針數(shù)組最常被用于處理多個(gè)字符串,雖然使用普通二維字符數(shù)組也可以存放和管理多個(gè)字符串(由于每個(gè)字符串都是一個(gè)一維字符數(shù)組,因此需要使用二維數(shù)組來存儲(chǔ)多個(gè)字符串),但是在效率方面要比使用指針數(shù)組低的多。主要理由如下:(1)使用二維數(shù)組存放多個(gè)字符串時(shí),由于二維護(hù)數(shù)組在定義時(shí)列數(shù)就是固定的,即每一行數(shù)組的元素個(gè)數(shù)相同,因此往往使用最長長度來定義二維數(shù)組的列數(shù)。而實(shí)際上每個(gè)字符串的長度可能是不等的,這樣就會(huì)造成內(nèi)存空間的浪費(fèi),例如:charstr[3][9]={“dog”,“duck”,“elephant”}在內(nèi)存中的存儲(chǔ)形式如圖9-15所示;而字符指針數(shù)組的各個(gè)指針元素只是指向各個(gè)一維字符數(shù)組,指針數(shù)組的長度與字符串的長度無關(guān),因此不存在內(nèi)存浪費(fèi)的問題。(2)使用二維數(shù)組來處理多個(gè)字符串時(shí),特別當(dāng)涉及字符串的交換、復(fù)制和排序等操作時(shí),需要將字符串整個(gè)進(jìn)行移動(dòng);而使用字符指針數(shù)組來處理這些操作時(shí),不必改變各字符串在內(nèi)存中的位置,只需改動(dòng)指針數(shù)組中各元素的指向就可以了。因此使用字符指針數(shù)組來處理多個(gè)字符串的效率要比二維字符數(shù)組高得多。例9-30編寫程序用來找出4個(gè)字符串中按字母排序最大的字符串/*exam9-30*/#include“stdio.h”#include“string.h”main(){ char﹡str[4]={“bee”,“dog”,“pig”,“elephant”}; inti,j,k; char﹡s; for(i=0;i<3;i++) { k=i; for(j=i+1;j<4;j++) { if(strcmp(str[k],str[j])>0)k=j; } if(k!

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論