版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第十章 主要內(nèi)容 10.1地址和指針的概念 10.變量的指針和指向變量的 指針變量 10.數(shù)組與指針 10.字符串與指針 10.指向函數(shù)的指針 10.返回指針值的函數(shù) 10.指針數(shù)組和指向指針的指針 10.8有關(guān)指針的數(shù)據(jù)類(lèi)型和指針運(yùn)算的小結(jié) 10.1地址和指針的概念(1)計(jì)算機(jī)硬件系統(tǒng)的內(nèi)存儲(chǔ)器中,擁有大量的存儲(chǔ)單元(容量為字節(jié))。為了方便管理,必須為每一個(gè)存儲(chǔ)單元編號(hào),這個(gè)編號(hào)就是存儲(chǔ)單元的“地址”。每個(gè)存儲(chǔ)單元都有一個(gè)惟一的地址。 1.內(nèi)存地址內(nèi)存中存儲(chǔ)單元的編號(hào)(2)在地址所標(biāo)識(shí)的存儲(chǔ)單元中存放數(shù)據(jù)。注意:內(nèi)存單元的地址與內(nèi)存單元中的數(shù)據(jù)是兩個(gè)完全不同的概念。2.變量地址系統(tǒng)分配給變量
2、的內(nèi)存單元的起始地址假設(shè)有這樣一個(gè)程序: main() int num; scanf(%d,&num); printf(num=%dn, num); C編譯程序編譯到該變量定義語(yǔ)句時(shí),將變量num 登錄到“符號(hào)表”中。符號(hào)表的關(guān)鍵屬性有兩個(gè):一是“標(biāo)識(shí)符名(id)” ,二是該標(biāo)識(shí)符在內(nèi)存空間中的“地址(addr)” 。為描述方便,假設(shè)系統(tǒng)分配給變量num的2字節(jié)存儲(chǔ)單元為 2000 和2001,則起始地址2000就是變量num在內(nèi)存中的地址。 3.變量值的存取通過(guò)變量在內(nèi)存中的地址進(jìn)行系統(tǒng)執(zhí)行“scanf(”%d“,&num);”和“printf(”num=%dn“, num);”時(shí),存取變量
3、num值的方式可以有兩種: (1)直接訪(fǎng)問(wèn)直接利用變量的地址進(jìn)行存取 1)上例中scanf(“%d”,&num)的執(zhí)行過(guò)程是這樣的: 用變量名num作為索引值,檢索符號(hào)表,找到變量num的起始地址2000;然后將鍵盤(pán)輸入的值(假設(shè)為)送到內(nèi)存單元2000和2001中。此時(shí),變量num在內(nèi)存中的地址和值 2)printf(num=%dn,num)的執(zhí)行過(guò)程,與scanf()很相似: 首先找到變量num的起始地址2000,然后從2000和2001中取出其值,最后將它輸出。 (2)間接訪(fǎng)問(wèn)通過(guò)另一變量訪(fǎng)問(wèn)該變量的值 語(yǔ)言規(guī)定:在程序中可以定義一種特殊的變量(稱(chēng)為指針變量),用來(lái)存放其它變量的地址。例
4、如,假設(shè)定義了這樣一個(gè)指針變量num_pointer,它被分配到4000、4001單元,其值可通過(guò)賦值語(yǔ)句“num_pointer=num;”得到。此時(shí),指針變量num_pointer的值就是變量num在內(nèi)存中的起始地址2000.通過(guò)指針變量num_pointer存取變量num值的過(guò)程如下:首先找到指針變量num_pointer的地址(4000),取出其值2000(正好是變量num 的起始地址); 然后從2000、2001中取出變量num的值(3)。 在語(yǔ)言中,指針是一種特殊的變量,它是存放地址的。(3)兩種訪(fǎng)問(wèn)方式的比較 兩種訪(fǎng)問(wèn)方式之間的關(guān)系,可以用某人甲(系統(tǒng))要找某人乙(變量)來(lái)類(lèi)比。
5、一種情況是,甲知道乙在何處,直接去找就是(即直接訪(fǎng)問(wèn))。另一種情況是,甲不知道乙在哪,但丙(指針變量)知道,此時(shí)甲可以這么做:先找丙,從丙處獲得乙的去向,然后再找乙(即間接訪(fǎng)問(wèn))。指針和指針變量的定義:一個(gè)變量的地址稱(chēng)為該變量的“指針”。例如,地址2000是變量的指針。如果有一個(gè)變量專(zhuān)門(mén)用來(lái)存放另一變量的地址(即指針),則它稱(chēng)為“指針變量”。上述的i_pointer就是一個(gè)指針變量。為表示指針變量和它指向的變量之間的關(guān)系,用指針運(yùn)算符“*”表示。 例如,指針變量num_pointer與它所指向的變量num的關(guān)系,表示為:*num_pointer,即*num_pointer等價(jià)于變量num。因此
6、,下面兩個(gè)語(yǔ)句的作用相同:num=3; /*將3直接賦給變量num*/num_pointer=# /*使num_pointer指向num */*num_pointer=3; /*將3賦給指針變量num_pointer所指向的變量*/ 10.2 變量的指針和指向變量的指 針變量10.1 定義一個(gè)指針變量定義指針變量的一般形式為基類(lèi)型 *指針變量名;下面都是合法的定義:float *pointer_; char *pointer_; 可以用賦值語(yǔ)句使一個(gè)指針變量得到另一個(gè)變量的地址,從而使它指向一個(gè)該變量。例如:pointer_;pointer_;在定義指針變量時(shí)要注意兩點(diǎn):指針變量前面的
7、“*”,表示該變量的類(lèi)型為指針型變量。例: float *pointer_1;指針變量名是pointer_1 ,而不是* pointer_1 。 (2) 在定義指針變量時(shí)必須指定基類(lèi)型。需要特別注意的是,只有整型變量的地址才能放到指向整型變量的指針變量中。下面的賦值是錯(cuò)誤的 float a; int * pointer_1; pointer_1=&a; 10.2.2 指針變量的引用 注意:指針變量中只能存放地址(指針),不要將一個(gè)整數(shù)(或任何其他非地址類(lèi)型的數(shù)據(jù))賦給一個(gè)指針變量。 例10. 通過(guò)指針變量訪(fǎng)問(wèn)整型變量#include voidmain ( ) int ,; int*pointe
8、r_, *pointer_; ; pointer_; /*把變量的地址賦給 pointer_1 */ pointer_; /*把變量的地址賦給 pointer_ */printf(%,%,);printf(%,%,*pointer_, *pointer_); 對(duì)“”和“*”運(yùn)算符說(shuō)明:如果已執(zhí)行了語(yǔ)句 pointer_;(1)* pointer_的含義是什么? “”和“*”兩個(gè)運(yùn)算符的優(yōu)先級(jí)別相同,但按自右而左方向結(jié)合。因此,* pointer_與相同,即變量a的地址。 如果有pointer_2 * pointer_ ;它的作用是將(的地址)賦給pointer_2 ,如果pointer_2原來(lái)
9、指向,經(jīng)過(guò)重新賦值后它已不再指向了,而指向了。(2) *的含義是什么? 先進(jìn)行運(yùn)算,得的地址,再進(jìn)行*運(yùn)算。*和*pointer_的作用是一樣的,它們都等價(jià)于變量。即*與等價(jià)。(3) (*pointer_)相當(dāng)于。例10 . 2 輸入和兩個(gè)整數(shù),按先大后小的順序輸出 和。#include void main() int *1,*2,*,; scanf(,);1; if();printf(=,=,); printf(max=,min=,*1,*2); 運(yùn)行情況如下:,當(dāng)輸入,時(shí),由于,將和交換。交換前的情況見(jiàn)圖(),交換后見(jiàn)圖()。注意:此例中a和b并未交換,而p1和p2的值改變。10.3 指針
10、變量作為函數(shù)參數(shù)例10 . 3 對(duì)輸入的兩個(gè)整數(shù)按大小順序輸出 #include void main()void swap(int *,int *);int ,;int *pointer_,*pointer_; scanf(,);pointer_ ; pointer_2 ; if()swap( pointer_ , pointer_2 );printf(,); void swap(int *,int *) int temp; temp*1; *; *temp; 注意:此例中a和b已經(jīng)交換,而pointer_ , pointer_2的值未改變。被調(diào)用函數(shù)不能改變實(shí)參指針變量的值,但可以改變它們所
11、指向的變量的值。為了利用被調(diào)用函數(shù)改變的變量值,應(yīng)該使用指針(或指針變量)作函數(shù)實(shí)參。其機(jī)制為:在執(zhí)行被調(diào)用函數(shù)時(shí),使形參指針變量所指向的變量的值發(fā)生變化;函數(shù)調(diào)用結(jié)束后,通過(guò)不變的實(shí)參指針(或?qū)崊⒅羔樧兞浚⒆兓闹当A粝聛?lái)。例10. 輸入、 3個(gè)整數(shù),按大小順序輸出。#include void main() void exchange(int *1, int *2, int *3); int ,*,*,*; scanf(%,%,%,&, &, &); exchange (,); printf(,); void exchange(int *, int *, int *) void swap(
12、int *, int *); if(*) swap(,); if(*) swap(,); if(* swap(,); void swap(int *, int *) int temp; temp*; *; *temp; 10.3 數(shù)組與指針 一個(gè)變量有地址,一個(gè)數(shù)組包含若干元素,每個(gè)數(shù)組元素都在內(nèi)存中占用存儲(chǔ)單元,它們都有相應(yīng)的地址。指針變量既然可以指向變量,當(dāng)然也可以指向數(shù)組元素(把某一元素的地址放到一個(gè)指針變量中)。所謂數(shù)組元素的指針就是數(shù)組元素的地址。 10.3.1 指向數(shù)組元素的指針數(shù)組的指針數(shù)組在內(nèi)存中的起始地址,數(shù)組元素的指針數(shù)組元素在內(nèi)存中的起始地址。2.指向數(shù)組的指針變量的定義
13、指向數(shù)組的指針變量的定義,與指向普通變量的指針變量的定義方法一樣。例如: ; (定義為包含個(gè)整型數(shù)據(jù)的數(shù)組)*; (定義為指向整型變量的指針變量)應(yīng)當(dāng)注意,如果數(shù)組為型,則指針變量的基類(lèi)型亦應(yīng)為型。 對(duì)該指針變量賦值:;把元素的地址賦給指針變量。也就是使指向數(shù)組的第號(hào)元素,如圖:在C中,數(shù)組名代表數(shù)組的首地址。因此p=a ; 與p=&a0;是等價(jià)的。p = a ; 是將a 數(shù)組的首地址賦給指針變量p。但這里的a 并不代表整個(gè)數(shù)組。上面定義可寫(xiě)成: int*p=a;作用是把a(bǔ)數(shù)組首元素地址賦給指針變量p(不是*p)10.通過(guò)指針引用數(shù)組元素 若p = a ; 是將整型數(shù)組a的首地址賦給整型指針變
14、量 p,則 *p=5; 是將整數(shù)5賦給a數(shù)組的第一個(gè)元素a0,等價(jià)于a0=5 。 p+1表示指針變量p當(dāng)前所指的數(shù)組元素的下一個(gè)元素。但p+1 不是p的值加 1 。若有 p=&a0; 則 p+i (或a+i) 就是 a i 的地址 (因?yàn)閍代表數(shù)組a的首地址)。 若有p=&a0; 則*(p+i)或*(a+i)就是p+i或a+i所指向的數(shù)組元素, 即ai。也就是說(shuō) *(p+i) = *(a+i) = ai。 指向數(shù)組的指針變量可以帶下標(biāo),如:pi 與 *( p+i)是等價(jià)的。引用一個(gè)數(shù)組元素,可以用:() 下標(biāo)法,如形式;() 指針?lè)?,?()或*()。其中是數(shù)組名,是指向數(shù)組元素的指針變量,其
15、初值。例10.5 輸出數(shù)組中的全部元素。 假設(shè)有一個(gè)數(shù)組,整型,有個(gè)元素。要輸出各元素的值有三種方法: (1)下標(biāo)法。#include void main() int ; int;for(;)scanf(,); printf();for(;)printf(,); (2) 通過(guò)數(shù)組名計(jì)算數(shù)組元素地址,找出元素的值。#include voidmain() int ; int ;for(; )scanf(,);printf(); for(;) printf(,*(); (3) 用指針變量指向數(shù)組元素。#include void main() int ; int *,; for(;) scanf(,)
16、; printf(); for(;();) printf( ,*); 這三種方法比較:1.前兩種效率相同,每次都要計(jì)算元素地址,費(fèi)時(shí)較多。2.第三種方法用指針變量直指元素,不必每次從新計(jì)算地址,像P+這樣的運(yùn)算速度很快,所以能大量提高執(zhí)行效率。3.下標(biāo)法比較直觀,能直接知道是第幾個(gè)元素,地址法或指針?lè)ú恢庇^,需要仔細(xì)分析地址和指針的指向。幾個(gè)注意的問(wèn)題:指針變量可以實(shí)現(xiàn)本身的值的改變。如p+是合法的;而a+是錯(cuò)誤的。因?yàn)閍是數(shù)組名,它是數(shù)組的首地址,是常量。要注意指針變量的當(dāng)前值。請(qǐng)看下面的程序:例10. 通過(guò)指針變量輸出數(shù)組的個(gè)元素。 #include void main() int*,;f
17、or(; )scanf(,); printf(); for(;, ) printf(,*);程序運(yùn)行情況:1 2 3 4 5 6 7 8 9 022153 234 0 0 30036 25202 11631 8259 8237 28483顯然輸出的數(shù)值并不是數(shù)組中各元素的值 #include void main() int*,;for(;)scanf(,); printg(); p=a; for(;, ) printf(,*);從上例可以看出,雖然定義數(shù)組時(shí)指定它包含10個(gè)元素,但指針變量可以指到數(shù)組以后的內(nèi)存單元,系統(tǒng)并不認(rèn)為非法。*p+,由于+和*同優(yōu)先級(jí),結(jié)合方向自右而左,等價(jià)于*(p+
18、)。*(p+)與*(+p)作用不同。若p的初值為a,則*(p+)等價(jià)a0,*(+p)等價(jià)a1。(*p)+表示p所指向的元素值加1。如果p當(dāng)前指向a數(shù)組中的第i個(gè)元素,則*(p-)相當(dāng)于ai-;*(+p)相當(dāng)于a+i;*(-p)相當(dāng)于a-i。10.3 用數(shù)組名作函數(shù)參數(shù)在第8章8.7節(jié)中介紹過(guò)可以用數(shù)組名作函數(shù)的參數(shù)如: void main() i(int arr,int ); int array; (array,); void (int arr,int ) array為實(shí)參數(shù)組名,arr為形參數(shù)組名。在學(xué)習(xí)指針變量之后就更容易理解這個(gè)問(wèn)題了。數(shù)組名就是數(shù)組的首地址,實(shí)參向形參傳送數(shù)組名實(shí)際上就
19、是傳送數(shù)組的地址,形參得到該地址后也指向同一數(shù)組。這就好象同一件物品有兩個(gè)彼此不同的名稱(chēng)一樣。 同樣,指針變量的值也 是地址,數(shù)組指針變量 的值即為數(shù)組的首地址 ,當(dāng)然也可作為函數(shù)的 參數(shù)使用。例10 將數(shù)組中個(gè)整數(shù)按相反順序存放。#include void main() void inv(int ,int ); int , ,;printf(The original array:);for(;)printf (,);printf(); inv (,); printf(The array has been in verted:); for(;) printf (,); printf ();vo
20、id inv(int ,int ) /*形參x是數(shù)組名*/ int temp,();for(;) ;temp; ; temp; return; 運(yùn)行情況如下:The original array:,The array has been inverted:,如果有一個(gè)實(shí)參數(shù)組,想在函數(shù)中改變此數(shù)組中的元素的值,實(shí)參與形參的對(duì)應(yīng)關(guān)系有以下種情況: (1) 形參和實(shí)參都用數(shù)組名,如:void main() void (int ,int ) int ; (,); (2) 實(shí)參用數(shù)組名,形參用指針變量。如:void () void (int *,int )int ; (,); (3)實(shí)參形參都用指針變量
21、。例如:void main() void (int *,int )int , *p=a; (p,); (4) 實(shí)參為指針變量,形參為數(shù)組名。如: void main() void (int x ,int ) ,*p=a; (p,); #include void main() void inv(int *,int ); int ,*; printf(The original array:n ); for(;,)scanf(,);printf(); ; inv(,); /* 實(shí)參為指針變量 ,一定 要有確定值*/ printf(The array has been inverted :); for
22、(; ) printf(,*); printf(); void inv(int *,int )int,temp,*,*;(); ;for(;,)emp*;*;*temp;return; 例109 用選擇法對(duì)個(gè)整數(shù)按由大到小順序排序。 #include void main() void sort(int ,int ); int*,10; ; for(;) scanf(,); ; sort(,); for(,;)(,*);void sort(int ,int )/*把x改為*x,下面不 int ,; 變,程序依然合法*/ for(;);for(;)() ; (?。?; ; ; 10.3.4 多維數(shù)組
23、與指針 用指針變量可以指向一維數(shù)組中的元素,也可以指向多維數(shù)組中的元素。但在概念上和使用上,多維數(shù)組的指針比一維數(shù)組的指針要復(fù)雜一些。 1. 多維數(shù)組元素的地址先回顧一下多維數(shù)組的性質(zhì),可以認(rèn)為二維數(shù)組是“數(shù)組的數(shù)組”,例 :定義int a34=0,1,2,3,4,5,6,7,8,9,10,11則二維數(shù)組a是由3個(gè)一維數(shù)組所組成的。設(shè)二維數(shù)組的首行的首地址為1 ,則各下標(biāo)變量的首地址及其值如圖所示。語(yǔ)言允許把一個(gè)二維數(shù)組分解為多個(gè)一維數(shù)組來(lái)處理。因此數(shù)組a可分解為三個(gè)一維數(shù)組,即a0,a1,a2。每一個(gè)一維數(shù)組又含有四個(gè)元素。數(shù)組及數(shù)組元素的地址表示如下:從二維數(shù)組的角度來(lái)看,a是二維數(shù)組名,
24、a代表整個(gè)二維數(shù)組的首地址,也是二維數(shù)組0行的首地址,等于1000。a+1代表第一行的首地址,等于1008。如圖:a0是第一個(gè)一維數(shù)組的數(shù)組名和首地址,因此也為1000。*(a+0)或*a是與a0等效的, 它表示一維數(shù)組a00 號(hào)元素的首地址,也為1000。&a00是二維數(shù)組a的0行0列元素首地址,同樣是1000。因此,a,a0,*(a+0),*a,&a00是相等的。同理,a+1是二維數(shù)組1行的首地址,等于1008。a1是第二個(gè)一維數(shù)組的數(shù)組名和首地址,因此也為1008。&a10是二維數(shù)組a的1行0列元素地址,也是1008。因此a+1,a1,*(a+1),&a10是等同的。由此可得出:a+i,
25、ai,*(a+i),&ai0是等同的。此外,&ai和ai也是相等的。因?yàn)樵诙S數(shù)組中不能把&ai理解為元素ai的地址,不存在元素ai。語(yǔ)言規(guī)定,它是一種地址計(jì)算方法,表示數(shù)組a第i行第0個(gè)元素的首地址。由此,我們得出:ai,&ai,*(a+i)和a+i也都是相等的。另外,a0也可以看成是a0+0,是一維數(shù)組a0的0號(hào)元素的首地址,而a0+1則是a0的1號(hào)元素首地址,由此可得出ai+j則是一維數(shù)組ai的j號(hào)元素首地址,它等于&aij。由ai=*(a+i)得ai+j=*(a+i)+j。由于*(a+i)+j是二維數(shù)組a的i行j列元素的首地址,所以,該元素的值等于*(*(a+i)+j)。定義int a
26、34=1,3,5,7,;則二維數(shù)組a是由3個(gè)一維數(shù)組所組成的。設(shè)二維數(shù)組的首行的首地址為 ,則表 示 形 式含義地 址a 二維數(shù)組名,指向一維數(shù)組a0,即0行首地址2000a0,*(a+0),*a0行0列元素地址2000a+1,&a11行首地址2008a1,*(a+1)1行0列元素a10的地址2008a1+2,*(a+1)+2,&a121行2列元素a12 的地址2012*(a1+2),*(*(a+1)+2),a121行2列元素a12的值元素值為13例10.0 輸出二維數(shù)組有關(guān)的值 #include define FROMAT,void main() int 341,3,5,7,9, ,; pr
27、intf(,*); printf(,0 , *();printf(,0,00);printf(,1,);printf(,10,*(+)+);printf(,*();printf(,); printf(,*(*( ); 某一次運(yùn)行結(jié)果如下:, (0行首地址和0行0列元素地址), (0行0列元素地址), (0行0首地址和0行0列元素地址), (1行0列元素地址和1行首地址), (1行0列元素地址), (2行0列元素地址), (2行首地址), (1行0列元素的值)2 . 指向多維數(shù)組元素的指針變量(1) 指向數(shù)組元素的指針變量例10.11 用指針變量輸出二維數(shù)組元素的值 #include void
28、main() int 341,3,5,7,9,11,13,15,17,19,21,23; int*; for(;) () printf(); printf(,*); 運(yùn)行結(jié)果如下:1 3 5 7 9 11 13 1519 21 23 把二維數(shù)組a分解為一維數(shù)組a0,a1,a2之后,設(shè)p為指向二維數(shù)組的指針變量。可定義為: int (*p)4它表示p是一個(gè)指針變量,它指向包含4個(gè)元素的一維數(shù)組。若指向第一個(gè)一維數(shù)組a0,其值等于a,a0,或&a00等。而p+i則指向一維數(shù)組ai。從前面的分析可得出*(p+i)+j是二維數(shù)組i行j 列的元素的地址,而*(*(p+i)+j)則是i行j列元素的值。(指
29、向數(shù)組元素的指針變量p求aij則需要用 i*m+j來(lái)求其位置。)二維數(shù)組指針變量說(shuō)明的一般形式為:類(lèi)型說(shuō)明符 (*指針變量名)長(zhǎng)度其中“類(lèi)型說(shuō)明符”為所指數(shù)組的數(shù)據(jù)類(lèi)型?!?”表示其后的變量是指針類(lèi)型?!伴L(zhǎng)度”表示二維數(shù)組分解為多個(gè)一維數(shù)組時(shí),一維數(shù)組的長(zhǎng)度,也就是二維數(shù)組的列數(shù)。應(yīng)注意“(*指針變量名)”兩邊的括號(hào)不可少,如缺少括號(hào)則表示是指針數(shù)組(本章后面介紹),意義就完全不同了。 (2) 指向由個(gè)元素組成的一維數(shù)組的指針變量例10.13 出二維數(shù)組任一行任一列元素的值#include void main ( ) int 1,3,5,7,9,11, 13,15,;int (*),; ;sc
30、anf( ,); printf(, ,*(*(); 運(yùn)行情況如下:,(本行為鍵盤(pán)輸入),3. 用指向數(shù)組的指針作函數(shù)參數(shù)例10.13 有一個(gè)班,個(gè)學(xué)生,各學(xué)門(mén)課,計(jì)算總平均分?jǐn)?shù)以及第個(gè)學(xué)生的成績(jī)。這個(gè)題目是很簡(jiǎn)單的。只是為了說(shuō)明用指向數(shù)組的指針作函數(shù)參數(shù)而舉的例子。用函數(shù)average求總平均成績(jī),用函數(shù)search找出并輸出第個(gè)學(xué)生的成績(jī)。#include void main() void average(float *p,int n); void search(float (*p)4,int n); float score34=65,67,70,60,80, 87,90,81,90,99,
31、100,98; average(*score,12);*求12個(gè)分?jǐn)?shù)的平均分*search(score,);*求序號(hào)為的學(xué)生的成績(jī)*void average(float *,int ) float*_; float sum,aver; p_end; for(;_;) sumsum(*); aversum; printf(average,aver);void search(float (*)4,int ) / * p是指向具有4個(gè)元素的一維數(shù)組的指針 */int ; printf(the score of No. % are:,); for(;) printf(5.2,*(*(); 程序運(yùn)行結(jié)果
32、如下:averageThe score of No.2 are:.例10.4 在上題基礎(chǔ)上,查找有一門(mén)以上課程不及格的學(xué)生,打印出他們的全部課程的成績(jī)。 #include void main()void search(float (*p)4,int n);/*函數(shù)聲明*/ float score34=65,57,70,60,58,87, 90,81,90,99,100,98; search(score,);void search(float (*p)4,int )int ,; for(;) flag; for(;) if(*(*())flag; if() printf(No.%d fails,
33、his scores are:n,j+1); for(;) printf(%.,*(*(); printf(); 程序運(yùn)行結(jié)果如下:No.1 fails, his scores are:. . . .No.2 fails, his scores are:. . . . 10. 字符串與指針10.4.字符串的表示形式 (1) 用字符數(shù)組存放一個(gè)字符串,然后輸出該字符串。例 10.5 定義一個(gè)字符數(shù)組,對(duì)它初始化, 然后輸出該字符串 #include void main()char stringI love China!; printf(,string); (2) 用字符指針指向一個(gè)字符串??梢圆?/p>
34、定義字符數(shù)組,而定義一個(gè)字符指針。用字符指針指向字符串中的字符。 例106 定義字符指針#include void main()char*string I love China??;printf(,);字符串指針變量的定義說(shuō)明與指向字符變量的指針變量說(shuō)明是相同的。只能按對(duì)指針變量的賦值不同來(lái)區(qū)別。對(duì)指向字符變量的指針變量應(yīng)賦予該字符變量的地址。如: char c,*p=&c;表示p是一個(gè)指向字符變量c的指針變量。而: char *ps=C Language;則表示s是一個(gè)指向字符串的指針變量。把字符串的首地址賦予s。上例中,首先定義string是一個(gè)字符指針變量,然后把字符串的首地址賦予stri
35、ng(應(yīng)寫(xiě)出整個(gè)字符串,以便編譯系統(tǒng)把該串裝入連續(xù)的一塊內(nèi)存單元),并把首地址送入string。程序中的:char *ps=C Language;等效于:char *ps;ps=C Language;從以上兩個(gè)例子中,可以看到:1、字符數(shù)組和字符指針的概念不同。2、字符指針指向字符串,而C語(yǔ)言中,字符串按數(shù)組方式處理,因此,字符數(shù)組和字符指針的訪(fǎng)問(wèn)方式相同。例如,均可以使用%s格式控制符進(jìn)行整體輸入輸出。但應(yīng)注意,如果不是字符數(shù)組,而是整型、實(shí)型等數(shù)字型數(shù)組,不能用%s,只能逐個(gè)元素處理。例10.7 將字符串復(fù)制為字符串。 #include void ()char am a boy,20; i
36、nt ; for(;*()??;) *()*(); *(); printf(string a is :,); printf(string b is:); for(;?。唬?printf(,); printf(); 也可以設(shè)指針變量,用它的值的改變來(lái)指向字符串中的不同的字符。 例10.8 用指針變量來(lái)處理例107問(wèn)題。#include void main() char =I am a boy. ,20,*p1,*p2; int ; ; for(;*?。籶1,p2)*;*;printf(string is:,); printf( :);for(;!;) printf(,); printf();程序必
37、須保證使和同步移動(dòng) 10.4.2 字符指針作函數(shù)參數(shù)將一個(gè)字符串從一個(gè)函數(shù)傳遞到另一個(gè)函數(shù),可以使用傳地址的方式,即用字符數(shù)組名或字符指針變量作參數(shù)。有以下四種情況: 實(shí)參 形參 數(shù)組名 數(shù)組名 數(shù)組名 字符指針變量 字符指針變量 字符指針變量 字符指針變量 數(shù)組名(1) 用字符數(shù)組作參數(shù)例10.19 用函數(shù)調(diào)用實(shí)現(xiàn)字符串的復(fù)制 #include void main() void copy_string(char from , char to ); char a = am a teacher; char =you are a student; printf(“string a= string
38、, ,); printf(“copy string a to string b:n ”); copy_string (,); printf(nstring a=%snstring b=%sn,a,b); void copy_string(char from , char to ) int ; while(from?。﹖ofrom;to; 程序運(yùn)行結(jié)果如下: string aI am a teacher string b you are a student copy string a to string b:string a I am a teacherstringI am a teacher(
39、2) 形參用字符指針變量 #include void main() void copy_string(char * from, char *); char * am a teacher .; char *you are a student ; printf(string a=string ,); printf(copy string a to string b:n ); _(,);printf(nstring a=%snstring b=%sn,a,b); void copy_string(char *,char *) for(;*from!;from,to)*to*from;*to; (3)
40、 對(duì)copy string 函數(shù)還可作簡(jiǎn)化 1、將copy_string函數(shù)改寫(xiě)為void copy_string (char *from,char *) while(*from)?。?to;from; copy_string函數(shù)的函數(shù)體還可改為 while(*to*from)?。?copy_string函數(shù)的函數(shù)體還可寫(xiě)成 while(*from?。?to*from; *to; 上面的while語(yǔ)句還可以進(jìn)一步簡(jiǎn)化為下面的while語(yǔ)句:while(*to*from);它與下面語(yǔ)句等價(jià):while(*to*from)?。?;將*from賦給*to,如果賦值后的*to值等于則循環(huán)終止(已賦給*
41、to) 函數(shù)體中while語(yǔ)句也可以改用for語(yǔ)句:for(;(*to*from)??;);或for(;*to*from;);也可用指針變量,函數(shù)copy_string可寫(xiě)為void copy_string (char from ,char )char*,*; from;while(*p2*p1)?。?;10.4.3 對(duì)使用字符指針變量和字符數(shù)組的討論字符數(shù)組和字符指針變量二者之間的區(qū)別:(1) 字符數(shù)組由若干個(gè)元素組成,每個(gè)元素中放一個(gè)字符,而字符指針變量中存放的是地址(字符串第1個(gè)字符的地址),決不是將字符串放到字符指針變量中。(2)賦值方式。對(duì)字符數(shù)組只能對(duì)各個(gè)元素賦值,不 能用以下辦法對(duì)字
42、符數(shù)組賦值。 char str; strI love China??; 而對(duì)字符指針變量,可以采用下面方法賦值: char*; I love China??; (3)對(duì)字符指針變量賦初值: char * love China?。坏葍r(jià)于 char*; I love Chian??; 而對(duì)數(shù)組的初始化: char str love China!; 不能等價(jià)于 char str; str I love China?。?4) 定義了一個(gè)字符數(shù)組,在編譯時(shí)為它分配內(nèi)存單元,它有確定的地址。而定義一個(gè)字符指針變量時(shí),給指針變量分配內(nèi)存單元,在其中可以放一個(gè)字符變量的地址。 例如: char str; scanf
43、(,str);(5) 指針變量的值是可以改變的,例如:例10.0改變指針變量的值#include void ()char*I love China??; ; printf(,); 若定義了一個(gè)指針變量,并使它指向一個(gè)字符串,就可以用下標(biāo)形式引用指針變量所指的字符串中的字符。例如: #include voidmain()char* love hina!; int ; printf ( “ The sixth character is %cn,a5); for(;!;) printf(,); 10. 指向函數(shù)的指針10.5.1 用函數(shù)指針變量調(diào)用函數(shù)函數(shù)的指針:函數(shù)的入口地址(函數(shù)的首地址)。C語(yǔ)言
44、規(guī)定函數(shù)的首地址就是函數(shù)名,所以函數(shù)名就是函數(shù)的指針。指向函數(shù)的指針變量:存放函數(shù)入口地址(函數(shù)指針)的變量,稱(chēng)為指向函數(shù)的指針變量。簡(jiǎn)稱(chēng)函數(shù)的指針變量。函數(shù)可以通過(guò)函數(shù)名調(diào)用,也可以通過(guò)函數(shù)指針調(diào)用。通過(guò)函數(shù)指針實(shí)現(xiàn)函數(shù)調(diào)用的步驟:1、指向函數(shù)的指針變量的定義: 類(lèi)型 (* 函數(shù)指針變量名)(); 例如 int (*p)(); 注意:兩組括號(hào)()都不能少。int表示被指向的函數(shù)的類(lèi)型,即被指向的函數(shù)的返回值的類(lèi)型。2、指向函數(shù)的指針變量的賦值,指向某個(gè)函數(shù): 函數(shù)指針變量名=函數(shù)名;3、利用指向函數(shù)的指針變量調(diào)用函數(shù):(* 函數(shù)指針變量名)(實(shí)參表)例:輸入10個(gè)數(shù),求其中的最大值。/* 使
45、用函數(shù)名調(diào)用函數(shù) */main()int i,m,a10; for(i=0; i10; i+) scanf(%d,&ai); m=max(a); /* 函數(shù)調(diào)用格式:函數(shù)名(實(shí)參表) */ printf(max=%dn,m);int max(int *p) /* max在10個(gè)整數(shù)中選擇最大值 */ int i,t=*p; for(i=1; it)t=*(p+i); return t;結(jié)果:-52 87 29 79 -32 94 23 -112 46 67max=94聲明函數(shù)/* 使用函數(shù)指針變量調(diào)用函數(shù) */main()int i,m,a10,max(int *); /* declare f
46、unc */ int (*pf)(); /* define func pointer */for(i=0; imax() */ m=(*pf)(a); /* call max */ printf(max=%dn,m);聲明函數(shù)指針的定義:定義函數(shù)指針變量pf(返回整型數(shù))指針的初始化:函數(shù)指針pf指向max指針的引用:調(diào)用函數(shù)指針pf指向的函數(shù)maxint max(int *p) int i,t=*p; for(i=1; it)t=*(p+i); return t;說(shuō)明:(1)定義函數(shù)指針變量時(shí),兩組括號(hào)()都不能少。如果少了前面的一組括號(hào)=返回值類(lèi)型 * 函數(shù)名();-返回值為地址值(指針)
47、的函數(shù)。(2)函數(shù)指針變量的類(lèi)型是被指向的函數(shù)的類(lèi)型,即返回值類(lèi)型。(3)函數(shù)指針的賦值,只要給出函數(shù)名,不必給出參數(shù)。(不要給出實(shí)參或形參)。(4)用指針變量調(diào)用函數(shù)時(shí),(* 函數(shù)指針)代替函數(shù)名。參數(shù)表與使用函數(shù)名調(diào)用函數(shù)一樣。(5)可以看出,定義的函數(shù)指針變量可以用于一類(lèi)函數(shù),只要這些函數(shù)返回值類(lèi)型(函數(shù)類(lèi)型)相同。函數(shù)可以通過(guò)函數(shù)名調(diào)用,也可以通過(guò)函數(shù)指針調(diào)用。函數(shù)指針常常用在函數(shù)需要作為函數(shù)參數(shù)的情況。 10.5.2 用指向函數(shù)的指針作函數(shù)參數(shù) 函數(shù)指針變量常用的用途之一是把指針作為參數(shù)傳遞到其他函數(shù)。指向函數(shù)的指針也可以作為參數(shù),以實(shí)現(xiàn)函數(shù)地址的傳遞,這樣就能夠在被調(diào)用的函數(shù)中使用
48、實(shí)參函數(shù)。函數(shù)的參數(shù)除了可以是變量、指向變量的指針,數(shù)組(實(shí)際是指向數(shù)組的指針)、指向數(shù)組的指針以外,還可以是函數(shù)的指針。函數(shù)的指針可以作為函數(shù)參數(shù),在函數(shù)調(diào)用時(shí)可以將某個(gè)函數(shù)的首地址傳遞給被調(diào)用的函數(shù),使這個(gè)被傳遞的函數(shù)在被調(diào)用的函數(shù)中調(diào)用(看上去好象是將函數(shù)傳遞給一個(gè)函數(shù))。函數(shù)指針的使用在有些情況下可以增加函數(shù)的通用性,特別是在可能調(diào)用的函數(shù)可變的情況下。 實(shí)參函數(shù)名 f1 void (int (*x1)(int),int (*x2)(int,int)) int ,; (*)(); *調(diào)用函數(shù)* (*)(,);*調(diào)用函數(shù)* 例10.3 設(shè)一個(gè)函數(shù)process,在調(diào)用它的時(shí)候,每次實(shí)現(xiàn)不
49、同的功能。輸入和兩個(gè)數(shù),第一次調(diào)用process時(shí)找出和中大者,第二次找出其中小者,第三次求與之和。 #include void main() int max(int,int); /* 函數(shù)聲明 */ int min(int,int); /* 函數(shù)聲明 */ int add(int,int); /* 函數(shù)聲明 */ void process (int , int , int(*fun)(); /* 函數(shù)聲明 */ int ,; printf(enter a and b:); scanf(,);printf(max); process(,);printf(min);process(,);prin
50、tf(sum);process(,);int max(int ,int ) /* 函數(shù)定義 */int ; if(); else ; return();int min(int ,int ) /* 函數(shù)定義 */ int ; if();else ;return(); int (int ,int ) /* 函數(shù)定義 */ int; ; return();void process(int ,int ,int (*fun)(int,int) int result; result(*fun)(,); printf(, result);(1)函數(shù)process處理兩個(gè)整數(shù)數(shù),并輸出一個(gè)值。同時(shí)又要求pro
51、cess具有通用處理能力(處理求大數(shù)、小數(shù)、和),所以可以考慮在調(diào)用process時(shí)將相應(yīng)的處理方法(“處理函數(shù)”)傳遞給process。(2)process函數(shù)要接受函數(shù)作為參數(shù),即process應(yīng)該有一個(gè)函數(shù)指針作為形式參數(shù),以接受函數(shù)的地址。這樣process函數(shù)的函數(shù)原型應(yīng)該是:int process(int x,int y,int (*f)();(3)“函數(shù)指針作為函數(shù)參數(shù)”的使用與前面介紹的步驟完全相同,即函數(shù)指針變量的定義-在通用函數(shù)process的形參定義部分實(shí)現(xiàn);函數(shù)指針變量的賦值-在通用函數(shù)的調(diào)用的虛實(shí)結(jié)合時(shí)實(shí)現(xiàn);用函數(shù)指針調(diào)用函數(shù)-在通用函數(shù)內(nèi)部實(shí)現(xiàn)。(4)main函數(shù)調(diào)
52、用通用函數(shù)process處理計(jì)算兩數(shù)中大數(shù)的過(guò)程是這樣的:l將函數(shù)名max(實(shí)際是函數(shù)max的地址)連同要處理的兩個(gè)整數(shù)a,b一起作為process函數(shù)的實(shí)參,調(diào)用process函數(shù)。lprocess函數(shù)接受來(lái)自主調(diào)函數(shù)main傳遞過(guò)來(lái)的參數(shù),包括兩個(gè)整數(shù)和函數(shù)max的地址,函數(shù)指針變量fun獲得了函數(shù)max的地址。l在process函數(shù)的適當(dāng)位置調(diào)用函數(shù)指針變量fun指向的函數(shù),即調(diào)用max函數(shù)。這樣調(diào)用點(diǎn)就獲得了兩數(shù)大數(shù)的結(jié)果,由printf函數(shù)輸出結(jié)果。 同樣,main函數(shù)調(diào)用通用函數(shù)process處理計(jì)算兩數(shù)小數(shù)、和的過(guò)程基本一樣。(5)process函數(shù)頭部:函數(shù)指針定義中不需要指定
53、形參個(gè)數(shù)。但是一般情況函數(shù)指針指向的函數(shù)參數(shù)個(gè)數(shù)一般是數(shù)量類(lèi)型相同的,以便用統(tǒng)一的格式如(*f)(x,y)去調(diào)用。process函數(shù)是一個(gè)“通用”整數(shù)處理函數(shù),它使用函數(shù)指針作為其中的一個(gè)參數(shù),以實(shí)現(xiàn)同一個(gè)函數(shù)中調(diào)用不同的處理函數(shù)。10. 返回指針值的函數(shù)一個(gè)函數(shù)可以帶回一個(gè)整型值、字符值、實(shí)型值等,也可以帶回指針型的數(shù)據(jù),即地址。其概念與以前類(lèi)似,只是帶回的值的類(lèi)型是指針類(lèi)型而已。這種帶回指針值的函數(shù),一般定義形式為類(lèi)型名 *函數(shù)名(參數(shù)表列);例如:int *(int ,int );例:返回兩個(gè)數(shù)中大數(shù)地址的函數(shù)。int *fun(int,int);main() int i,j,*p; p
54、rintf(enter two num to i,j:); scanf(%d%d,&i,&j); p=fun(i,j); /* 調(diào)用fun,返回大數(shù)地址,賦值給指針變量p */printf(max=%dn,*p); /* 打印p指向的數(shù)據(jù) */int *fun(int x,int y) /* fun函數(shù)返回形參x,y中較大數(shù)的地址(指針) */ int *z; if(xy)z=&x; else z=&y; return z;結(jié)果:enter two num to i,j:12 38max=38說(shuō)明:(1)main函數(shù)從鍵盤(pán)獲得兩個(gè)整數(shù)i,j(本例12,38)。將i,j作為實(shí)參調(diào)用fun。(2)
55、通過(guò)虛實(shí)結(jié)合,fun函數(shù)的形參x,y獲得了這兩個(gè)整數(shù)(本例12,38),將大數(shù)的地址返回(本例是&y)。(3)返回的地址值賦值給main函數(shù)的指針變量p,main函數(shù)打印p指向的整型數(shù),即y的值。例104 有若干個(gè)學(xué)生的成績(jī)(每個(gè)學(xué)生有門(mén)課程),要求在用戶(hù)輸入學(xué)生序號(hào)以后,能輸出該學(xué)生的全部成績(jī)。用指針函數(shù)來(lái)實(shí)現(xiàn)。 #include void main()float *score 4=60,70,80,90, 56,89,67,88,34,78,90,66; float*search(float (*pointer)4,int n); float*; int ,; printf(enter t
56、he number of student:); scanf(,); printf(The scores of No are:,); search(,);for(;printf(,*(); float * search(float (*)4,int ) float *; *(); return(); 運(yùn)行情況如下:enter the number of student:The scores of No. are:56.00 89.00 67.00 88.00例10.5 對(duì)上例中的學(xué)生,找出其中有不及格課程的學(xué)生及其學(xué)生號(hào)。#include void main()float score 4=60,
57、70,80,90,56, 89,67,88,34,78,90,66; float search(float (*pointer)4); float*; i ,; for(;)search(score );(*(score)printf(scores:,); for(;) printf(5.2,*(); printf(); float * search(float (*)4) float *; *(1); for(i=0;i4;i+) if(*(*pointer+i)60)pt=*pointer; return(); 10.7 指針數(shù)組和指向指針的指針10.7.1 指針數(shù)組的概念一個(gè)數(shù)組,若其元
58、素均為指針類(lèi)型數(shù)據(jù),稱(chēng)為指針數(shù)組,也就是說(shuō),指針數(shù)組中的每一個(gè)元素都相當(dāng)于一個(gè)指針變量。一維指針數(shù)組的定義形式為:類(lèi)型名*數(shù)組名數(shù)組長(zhǎng)度;例如:*;定義一個(gè)4個(gè)元素的數(shù)組p,其中每個(gè)元素是一個(gè)整型指針,也即數(shù)組p是一個(gè)4元素整型指針數(shù)組。又如:char *p4;定義一個(gè)4個(gè)元素的字符指針數(shù)組p,其中每個(gè)數(shù)組元素是一個(gè)字符指針,可以指向一個(gè)字符串。也就是說(shuō)利用此字符指針數(shù)組可以指向4個(gè)字符串。指針數(shù)組用得最多的是“字符型指針數(shù)組”,利用字符指針數(shù)組可以指向多個(gè)長(zhǎng)度不等的字符串,使字符串處理更加方便、靈活,節(jié)省內(nèi)存空間。使用字符型指針數(shù)組指向多個(gè)字符串 (上頁(yè)下圖)使用字符型指針數(shù)組指向多個(gè)字符串
59、與使用兩維字符數(shù)組存儲(chǔ)多個(gè)字符串的比較:(1)節(jié)省存儲(chǔ)空間(二維數(shù)組要按最長(zhǎng)的串開(kāi)辟存儲(chǔ)空間)(2)便于對(duì)多個(gè)字符串進(jìn)行處理,節(jié)省處理時(shí)間。(使用指針數(shù)組排序各個(gè)串不必移動(dòng)字符數(shù)據(jù),只要改變指針指向的地址)例10.6 將若干字符串按字母順序(由小到大)輸出。#include #include void main()void sort(char *name ,int n); void printf(char *name ,int n); char *name =Follow me,BASIC,Great Wall,F(xiàn)ORTRAN,Computer design; int ;sort(,); pr
60、int(,);void sort(char * ,int )char *; int ,; for(; for(; if(strcmp(name,name)0)=; if(!) temp=namei; namei=namek; namek=temp; void print(char * ,int ) ; (;) printf(,); 運(yùn)行結(jié)果為:Computer designFORTRANFollow meGreat Wall10.7.2 指向指針的指針指針的指針:指向指針變量的指針變量。指針的指針存放的是指針變量地址.指針變量的指針變量(指針的指針)的定義:類(lèi)型 *指針變量名; P2 p1 i
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 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ì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度生態(tài)旅游區(qū)開(kāi)發(fā)承包合同范本3篇
- 二零二五年度棉被租賃服務(wù)合同4篇
- 二零二五版影視基地拍攝場(chǎng)地租賃協(xié)議3篇
- 2025年度電梯安裝工程安全生產(chǎn)教育與培訓(xùn)協(xié)議4篇
- 二零二五年度藝術(shù)品投資擔(dān)保服務(wù)協(xié)議3篇
- 二零二五年度精密工件打磨工勞動(dòng)權(quán)益保護(hù)與職業(yè)發(fā)展合同4篇
- 二零二五版美甲店與知名品牌聯(lián)營(yíng)合作協(xié)議3篇
- 2025年中國(guó)有線(xiàn)燃?xì)鈭?bào)警器行業(yè)市場(chǎng)發(fā)展前景及發(fā)展趨勢(shì)與投資戰(zhàn)略研究報(bào)告
- 2025年藥用鋁箔項(xiàng)目可行性研究報(bào)告
- 二零二五年度智能物流倉(cāng)儲(chǔ)管理系統(tǒng)開(kāi)發(fā)與應(yīng)用合同3篇
- 副總經(jīng)理招聘面試題與參考回答(某大型國(guó)企)2024年
- PDCA循環(huán)提高護(hù)士培訓(xùn)率
- 2024-2030年中國(guó)智慧水務(wù)行業(yè)應(yīng)用需求分析發(fā)展規(guī)劃研究報(bào)告
- 《獅子王》電影賞析
- 河北省保定市定州市2025屆高二數(shù)學(xué)第一學(xué)期期末監(jiān)測(cè)試題含解析
- 中醫(yī)護(hù)理人文
- 2024-2030年中國(guó)路亞用品市場(chǎng)銷(xiāo)售模式與競(jìng)爭(zhēng)前景分析報(bào)告
- 貨物運(yùn)輸安全培訓(xùn)課件
- 前端年終述職報(bào)告
- 2024小說(shuō)推文行業(yè)白皮書(shū)
- 市人民醫(yī)院關(guān)于開(kāi)展“改善就醫(yī)感受提升患者體驗(yàn)主題活動(dòng)”2023-2025年實(shí)施方案及資料匯編
評(píng)論
0/150
提交評(píng)論