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

下載本文檔

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

文檔簡(jiǎn)介

第7章指針7.1指針和變量7.2指針和數(shù)組7.3指針和函數(shù)7.4指針的綜合示例本章小結(jié)

指針是C語(yǔ)言中廣泛使用的一種數(shù)據(jù)類(lèi)型,指針的使用極大地豐富了C語(yǔ)言的功能。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu),能很方便地使用數(shù)組和字符串,能像低級(jí)語(yǔ)言一樣處理內(nèi)存地址,從而編寫(xiě)出精練而高效的程序。學(xué)習(xí)C語(yǔ)言,只有深入理解和掌握指針,才能領(lǐng)會(huì)到C語(yǔ)言的精華所在,能否正確理解和使用指針也成為衡量是否掌握C語(yǔ)言的一個(gè)重要標(biāo)志。

7.1指針和變量

7.1.1指針的基本概念1.地址的概念與取地址運(yùn)算在計(jì)算機(jī)中,數(shù)據(jù)都是存放在存儲(chǔ)器中的。如果在程序中定義了一個(gè)變量,在編譯的時(shí)候就會(huì)給這個(gè)變量分配相應(yīng)的內(nèi)存單元。為了能正確地訪(fǎng)問(wèn)這些內(nèi)存單元,對(duì)每個(gè)內(nèi)存單元進(jìn)行編號(hào)(每個(gè)內(nèi)存單元具有唯一的編號(hào)),這樣,根據(jù)這個(gè)內(nèi)存單元的編號(hào)就可以準(zhǔn)確地找到該內(nèi)存單元。這個(gè)編號(hào)就稱(chēng)為地址。

至于這些變量放在內(nèi)存的什么地方,這都是機(jī)器的事,用戶(hù)只需知道它們是以怎樣的順序放在內(nèi)存中的,以便一一按順序引用即可。那么怎樣知道機(jī)器將某種數(shù)據(jù)放在內(nèi)存的什么地方呢?可用取地址運(yùn)算符“&”來(lái)獲取地址,例如,定義

inta=10;

則“&a”就代表獲取變量a在內(nèi)存中的地址。因?yàn)槿〉刂愤\(yùn)算符“&”就是取其后變量的地址??梢杂靡韵麓a看出其地址:

printf("%p\n",&a);

C語(yǔ)言規(guī)定:如果變量占用連續(xù)的多個(gè)字節(jié),則第一個(gè)字節(jié)的地址就是該變量的地址。變量在定義后,編譯器會(huì)給變量分配內(nèi)存空間,但不同編譯器的內(nèi)存分配方式不一定相同。假設(shè)定義:

floatb=10;

shorta=10;

則其內(nèi)存分配情況如圖7-1所示。

圖7-1變量分配的內(nèi)存示意圖

2.指針變量

使用一個(gè)變量可以直接通過(guò)變量名,這種方式稱(chēng)為“直接存取方式”。此外,還可以將變量的地址存入另一“特殊”變量中,然后通過(guò)該“特殊”變量來(lái)存取變量的值,這種存取變量的方式稱(chēng)為“間接存取方式”。而存放地址的變量就好像存放了一個(gè)指針,指向要存取值的變量,故稱(chēng)為“指針變量”,可完整地稱(chēng)為“指向變量的指針變量”。

如圖7-2所示,變量a的地址是2000,變量p的地址是8000,而變量p中存放的值2000是變量a在內(nèi)存中的地址。根據(jù)這一特點(diǎn)可以畫(huà)出如圖7-2所示的一種指向關(guān)系,地址2000可形象化地稱(chēng)為指針。從本例來(lái)看,2000是一個(gè)指針,但它實(shí)質(zhì)上是變量a的地址。所以說(shuō),指針其實(shí)就是變量的地址。另外,指針(或地址)2000存放在一個(gè)變量p中,由于這個(gè)變量p存放的不是一般類(lèi)型的數(shù)據(jù),而是指針(地址),所以稱(chēng)為“指針變量”。在這里,由于指針變量p指向變量a,所以完整地說(shuō),p是指向(普通)變量的指針變量。圖7-2變量a與指針變量p的關(guān)系

變量的地址雖然在形式上好像類(lèi)似于整數(shù),但在概念上不同于以前介紹過(guò)的整數(shù),它屬于一種新的數(shù)據(jù)類(lèi)型,即指針類(lèi)型。在C語(yǔ)言中,一般用“指針”來(lái)指明表達(dá)式&x的類(lèi)型,而用“地址”作為它的值,也就是說(shuō),若x為一整型變量,則表達(dá)式&x的類(lèi)型是指向整型變量的指針,而&x的值是變量x的地址。同樣,若定義:

doubled;

則&d的類(lèi)型是指向雙精度數(shù)d的指針,而&d的值是雙精度變量d的地址。

嚴(yán)格地說(shuō),“指針”和“指針變量”是兩個(gè)不同的概念。指針是一個(gè)地址,是一個(gè)常量。而指針變量是指存放地址的變量,可以被賦予不同的指針值,是一個(gè)變量。

定義指針的目的是為了通過(guò)指針去訪(fǎng)問(wèn)內(nèi)存單元。既然指針變量的值是一個(gè)地址,那么這個(gè)地址不僅可以是變量的地址,也可以是其他數(shù)據(jù)結(jié)構(gòu)(如數(shù)組、函數(shù))的地址。為什么在一個(gè)指針變量中存放一個(gè)數(shù)組或一個(gè)函數(shù)的首地址呢?因?yàn)閿?shù)組或函數(shù)都是連續(xù)存放的,通過(guò)訪(fǎng)問(wèn)指針變量取得了數(shù)組或函數(shù)的首地址,也就找到了該數(shù)組或函數(shù)。這樣凡是出現(xiàn)數(shù)組或者函數(shù)的地方都可以用一個(gè)指針變量來(lái)表示,只要該指針變量中賦予數(shù)組或函數(shù)的首地址即可。這樣做,將會(huì)使程序的概念十分清楚,程序本身也更精煉、高效。

在C語(yǔ)言中,一種數(shù)據(jù)類(lèi)型或數(shù)據(jù)結(jié)構(gòu)往往都占有一組連續(xù)的內(nèi)存單元。用“地址”這個(gè)概念并不能很好地描述一種數(shù)據(jù)類(lèi)型或數(shù)據(jù)結(jié)構(gòu),而“指針”雖然實(shí)際上也是一個(gè)地址,但它卻是一個(gè)數(shù)據(jù)結(jié)構(gòu)的首地址,它是“指向”一個(gè)數(shù)據(jù)結(jié)構(gòu)的,因而概念更為清楚,表示更為明確。這也是引入“指針”概念的一個(gè)重要原因。

7.1.2指針變量的定義與引用

1.指針變量的定義

指針變量也和普通變量一樣,必須“先定義,后使用”。但指針變量不同于普通變量,如前所述,指針變量是用于存放地址的變量,所以在定義時(shí),必須定義成“指針類(lèi)型”。指針變量的定義格式如下:

類(lèi)型說(shuō)明符*指針變量名[=初值];

例如:

int*p;

定義一個(gè)指針變量p,p指向的變量的數(shù)據(jù)類(lèi)型為整型(int)。

在定義指針變量時(shí),應(yīng)注意以下幾點(diǎn):

(1)類(lèi)型說(shuō)明符表示該指針變量所指向的變量的數(shù)據(jù)類(lèi)型,如int、float、double、char等。

(2)定義指針變量時(shí),指針變量名前必須有一個(gè)“*”號(hào),表示定義的變量是指針變量。

(3)指針變量在定義時(shí)允許對(duì)其賦初值。如:

inta=8;

int*p=&a;

值得注意的是,這里是用&a對(duì)p初始化,而不是對(duì)*p初始化。初始化后指針變量p中存放的是整型變量a的地址,如圖6-3所示。

圖7-3指針變量p與整型變量a的關(guān)系

為避免混淆,上述定義可以改寫(xiě)成

inta=8;

int*p;

p=&a;

這樣就能很容易看出,&a是賦給p,而不是賦給*p的。這個(gè)千萬(wàn)要搞清楚,因?yàn)閜和*p表示的含義是完全不同的。

必須注意的是,一個(gè)指針變量只能指向相同類(lèi)型的變量,如p2只能指向float類(lèi)型的變量,不能時(shí)而指向一個(gè)float類(lèi)型的變量,時(shí)而又指向一個(gè)int或char類(lèi)型的變量。

指針變量和普通變量一樣,在使用前要先定義,然后進(jìn)行賦值。未經(jīng)賦值的指針變量不能使用,否則將造成系統(tǒng)混亂,甚至死機(jī),因?yàn)樵诙x指針變量而沒(méi)有給它賦值之前,指針變量的值是不確定的。指針變量只能獲得地址值,絕不能賦予任何其他數(shù)據(jù),否則將引起錯(cuò)誤。

2.指針變量的引用

引用指針變量時(shí)常用到下面兩個(gè)重要的運(yùn)算符。

(1)?&:取地址運(yùn)算符。如p=&a,表示p存放變量a的地址?!?”號(hào)后能接任何類(lèi)型的變量(包括指針變量)。

(2)?*:取內(nèi)容運(yùn)算符,后面只能接指針變量,用于訪(fǎng)問(wèn)指針變量所指向的變量?;蛘哒f(shuō),以運(yùn)算對(duì)象的值作為地址,并返回這個(gè)地址所指變量(或內(nèi)存單元)的內(nèi)容。如*p表示訪(fǎng)問(wèn)指針變量p所指向的變量的內(nèi)容。

如果定義:

inta=8,b;

int*p;

p=&a;

則指針變量p指向整型變量a,如圖7-4所示。

圖7-4直接訪(fǎng)問(wèn)與間接訪(fǎng)問(wèn)

此時(shí),對(duì)整型變量a有兩種訪(fǎng)問(wèn)方式:

①直接訪(fǎng)問(wèn),如“b=a;”。

②通過(guò)指針變量間接訪(fǎng)問(wèn),如“b=*p;”。

表7-1列出了對(duì)整型變量a和指針變量p進(jìn)行引用的常用方法(參照?qǐng)D7-4的定義)。

7.1.3指針的運(yùn)算

1.指針移動(dòng)(和整型表達(dá)式進(jìn)行運(yùn)算)

在使用指針過(guò)程中,通過(guò)移動(dòng)指針來(lái)實(shí)現(xiàn)對(duì)不同數(shù)據(jù)單元的訪(fǎng)問(wèn)操作。對(duì)不同的類(lèi)型,移動(dòng)的單位長(zhǎng)度不同。單位長(zhǎng)度一般是指針?biāo)赶虻淖兞康臄?shù)據(jù)類(lèi)型長(zhǎng)度。下面是指針參與運(yùn)算時(shí)實(shí)現(xiàn)指針移動(dòng)的3種常用表達(dá)式格式。

格式一:p?=?p?+?n;(或p=p-n;)

格式二:p++;(或p--;)

格式三:++p;(或--p;)

其中,n是一個(gè)整數(shù),也可以是一個(gè)整型表達(dá)式。格式一的作用是使指針p向前(或向后)移動(dòng)n個(gè)單位長(zhǎng)度;而格式二和格式三的作用都是使指針p向前(或向后)移動(dòng)1個(gè)單位長(zhǎng)度。例如,定義:

shortb=20,a=10,*p=&a;

之后,假設(shè)內(nèi)存分配如圖7-5所示,這時(shí)p=&a=2000,執(zhí)行語(yǔ)句“p++;”之后,指針變量p的值是否為2000?+?1?=?2001呢?答案是否定的。因?yàn)橹羔樧兞康闹导?(或減1),并不是地址值加1(或減1),而是加上(或減去)1個(gè)單位長(zhǎng)度,即該指針?biāo)赶虻淖兞康臄?shù)據(jù)類(lèi)型長(zhǎng)度,也就是指針?biāo)赶虻淖兞吭趦?nèi)存中所占的字節(jié)數(shù),所以執(zhí)行p++之后,指針變量p的值不是2000?+?1?=?2001,而是加short類(lèi)型長(zhǎng)度2,即2000?+?2?=?2002。

圖7-5指針的移動(dòng)

2.指針賦值

指針變量因?yàn)槭谴娣拍繕?biāo)變量地址的變量,因此可以通過(guò)指針變量間接存取目標(biāo)變量。指針變量可以進(jìn)行某些運(yùn)算,但其運(yùn)算的種類(lèi)是有限的。它只能進(jìn)行賦值運(yùn)算和部分算術(shù)運(yùn)算及關(guān)系運(yùn)算。

1)指針運(yùn)算符

指針運(yùn)算符包括取地址運(yùn)算符和取內(nèi)容運(yùn)算符。

在指針變量說(shuō)明中,“*”是類(lèi)型說(shuō)明符,表示其后的變量是指針類(lèi)型。而其他表達(dá)式中出現(xiàn)的“*”則是一個(gè)運(yùn)算符,用以表示指針變量所指的變量。

例7-1通過(guò)指針訪(fǎng)問(wèn)簡(jiǎn)單變量。

上述程序中,語(yǔ)句“int*p=&a;”中的*p表示定義了一個(gè)指向整型變量的指針變量p,且指針變量p存放了整型變量a的地址。語(yǔ)句“printf("%d",*p);”中的*p表示p所指向的變量中的內(nèi)容,由于指針變量p中存放了a的地址,故本語(yǔ)句表示輸出指針變量p所指向的變量a的值,結(jié)果應(yīng)為12。

若已有“inta=12,*p=&a;”定義,那么“&*p”和“*&a”的含義是什么呢?

“&”和“*”運(yùn)算符的優(yōu)先級(jí)別相同,其結(jié)合方向?yàn)樽杂抑磷?,故?*p”中,應(yīng)先執(zhí)行“*p”的運(yùn)算,它的結(jié)果就是變量a,再執(zhí)行“&”運(yùn)算,即執(zhí)行“&a”,所以“&*p”就是“&a”,結(jié)果為a的地址。

同理,在執(zhí)行“*&a”時(shí),應(yīng)先執(zhí)行“&a”,結(jié)果為a的地址,再進(jìn)行“*”的運(yùn)算,即&a所指向的變量,“*&a”和“*p”的作用是一樣的,結(jié)果都是變量a。

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

將一個(gè)指針變量的值賦給另一個(gè)指針變量,結(jié)果是兩個(gè)指針指向同一個(gè)地址單元。例如:

inta=10,*p,*q;

p=&a;q=p;

則指針變量p和q的值都是變量a的地址,也就是說(shuō),指針變量p和q指向了同一個(gè)變量a,如圖7-6所示。

圖7-6指針的賦值

例7-3寫(xiě)出下面程序的運(yùn)行結(jié)果。

本程序的一次運(yùn)行結(jié)果為

指針p的值為009CFA24

指針p所指向的變量的值為*p=10

指針p的值賦給指針q后,指針q的值為q=009CFA24

指針p的值賦給指針q后,指針q所指向的變量的值為*q=10

例7-4輸入a和b兩個(gè)整數(shù),按從大到小的次序輸出。

若輸入10和20,則程序運(yùn)行結(jié)果為

10,20

a=10,b=20

*pa=10,*pb=20

a=10,b=20

*pa=20,*pb=10

由上述結(jié)果可見(jiàn),a和b并沒(méi)有交換,它們還是保持原來(lái)的數(shù)據(jù)不變,但指針變量pa和pb的值改變了。if語(yǔ)句執(zhí)行前,pa原來(lái)指向a,pb指向b,當(dāng)執(zhí)行后,pa和pb的值互換,而a和b不變。這樣在輸出*pa和*pb時(shí),實(shí)際輸出的是變量b和a的值,所以輸出時(shí)先輸出b的值20,再輸出a的值10。

例7-5改寫(xiě)例7-4。

同樣輸入10和20,程序運(yùn)行結(jié)果為

10,20

a=10,b=20

*pa=10,*pb=20

a=20,b=10

*pa=20,*pb=10

由上述結(jié)果可見(jiàn),a和b交換了。if語(yǔ)句執(zhí)行前,pa原指向a,pb指向b,*pa和*pb的值分別為10和20,當(dāng)執(zhí)行后,指針變量pa和pb所指向的變量的值互換,即把a(bǔ)和b的值互換了,使得a為20,b為10,這樣在輸出*pa和*pb時(shí),實(shí)際輸出的是變量a和b的值,所以輸出時(shí)先輸出a的值20,再輸出b的值10。

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

若有如下定義語(yǔ)句:

floatx,y,*p1,*p2;

p1=&x;

p2=&y;

假設(shè)指針變量p1和p2都指向相同類(lèi)型,如整型變量或常量n,則可以進(jìn)行如下算術(shù)運(yùn)算:

(1)自加自減運(yùn)算p1++、p1--。

p1++的作用是將指針變量的值指向相鄰的下一個(gè)同類(lèi)型單元。按以上的定義,則可知執(zhí)行p1++后p1值加4,指向下一個(gè)類(lèi)型為float的變量。p1++所代表的地址實(shí)際上是p1+

1?×?d,d是p1所指向數(shù)據(jù)的類(lèi)型所占的字節(jié)數(shù)(對(duì)于整型d=4,對(duì)于單精度浮點(diǎn)型d=4,對(duì)于雙精度浮點(diǎn)型d=8,對(duì)于字符型d=1)。

同理,p1--的作用是將指針變量的值指向相鄰的上一個(gè)同類(lèi)型單元。p1--所代表的地址實(shí)際上是p1-1?×?d,d是p1所指向數(shù)據(jù)的類(lèi)型所占的字節(jié)數(shù)。

(2)加減整型量p1+n、p1-n。

p1+n的作用是將指針變量的值指向向下第n個(gè)同類(lèi)型單元。p1+n所代表的地址實(shí)際上是p1+n?×?d(d的取值同上)。

p1-n的作用是將指針變量的值指向向上第n個(gè)同類(lèi)型單元。p1-n所代表的地址實(shí)際上是p1-n?×?d(d的取值同上)。

(3)同類(lèi)型指針相減。

C語(yǔ)言允許兩個(gè)指向相同類(lèi)型的指針變量相減,其結(jié)果是兩指針變量所指向的兩地址間同類(lèi)型的數(shù)據(jù)的個(gè)數(shù)。實(shí)際上是兩個(gè)指針值(地址)相減之差再除以該數(shù)組元素的長(zhǎng)度(字節(jié)數(shù))。

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

兩個(gè)指向相同類(lèi)型的指針變量也可進(jìn)行關(guān)系運(yùn)算,可支持>、<、>=、<=、==和!=共6種運(yùn)算,其運(yùn)算結(jié)果可以反映兩指針變量所指向單元在內(nèi)存中的分配地址之間的關(guān)系。若p1<p2成立,則p1所指向單元在p2所指向單元之前;若p1>p2成立,則p1所指向單元在p2所指向單元之后;若p1==p2成立,則p1和p2指向同一存儲(chǔ)單元。

指針變量還可以與0比較。設(shè)p為指針變量,則p==0表明p是空指針,它不指向任何變量;p!=0表示p不是空指針??罩羔樖怯蓪?duì)指針變量賦予0值而得到的。

例如:

#defineNULL0

int*p=NULL;

對(duì)指針變量賦0值和不賦值是不同的。指針變量未賦值時(shí),可以是任意值,是不能使用的,否則將造成意外錯(cuò)誤。而指針變量賦0值后,則可以使用,只是它不指向具體的變量而已。

7.2指針和數(shù)組

數(shù)組在內(nèi)存中占用連續(xù)的存儲(chǔ)空間,數(shù)組名代表的是數(shù)組的首地址??啥x一個(gè)指針變量,通過(guò)賦值或函數(shù)調(diào)用參數(shù)傳遞的方式,把數(shù)組名或數(shù)組的第一個(gè)元素的地址賦值給該指針變量,該指針變量就指向了該數(shù)組首元素。當(dāng)一個(gè)指針指向數(shù)組首元素后,對(duì)數(shù)組所有元素的訪(fǎng)問(wèn),既可以使用數(shù)組下標(biāo),也可以使用指針。

這里特別注意,指向數(shù)組元素的指針與指向數(shù)組的指針是兩個(gè)不同的概念:如果指針只是指向數(shù)組中的某個(gè)元素,指針移動(dòng)以元素為單位,則該指針是指向數(shù)組元素的指針;而如果指針指向的是某個(gè)數(shù)組,指針移動(dòng)以數(shù)組為單位,則該指針是指向數(shù)組的指針。

7.2.1指向數(shù)組元素的指針

定義一個(gè)指針變量,讓這個(gè)指針變量存儲(chǔ)數(shù)組中某個(gè)數(shù)組元素的地址,則該指針便指向了數(shù)組元素。通過(guò)該指針變量可對(duì)數(shù)組中的元素進(jìn)行各種操作。

1.使指針變量指向數(shù)組元素的方法

使指針變量指向數(shù)組元素的方法有以下兩種。

(1)在定義的同時(shí)為指針變量賦初值。例如:

(2)在程序的執(zhí)行語(yǔ)句部分為指針變量賦值。例如:

請(qǐng)讀者自行比較上述兩種方法,加深對(duì)指針定義及賦值的理解。

執(zhí)行上述定義后的內(nèi)存狀態(tài)如圖7-7和圖7-8所示。

圖7-7指向一維數(shù)組元素的指針變量

圖7-8指向二維數(shù)組元素的指針變量

例7-6利用指針,實(shí)現(xiàn)數(shù)組首元素和末元素值的交換。

程序運(yùn)行結(jié)果為

交換前數(shù)組值為:109876

交換后數(shù)組值為:698710

本程序中定義了兩個(gè)與數(shù)組數(shù)據(jù)類(lèi)型相同的指針p1和p2,這兩個(gè)指針可以指向數(shù)組中的任意元素,只要通過(guò)數(shù)組元素的地址進(jìn)行賦值即可,例如,p1=&a[0],p2=&a[4],這樣對(duì)*p1和*p2的操作就等效于對(duì)數(shù)組元素a[0]和a[4]的操作。

2.通過(guò)指針引用一維數(shù)組元素

當(dāng)指針p指向一維數(shù)組中某個(gè)元素時(shí),可以用指針p訪(fǎng)問(wèn)一維數(shù)組的所有元素。

1)指向一維數(shù)組首元素的指針

假設(shè)指針p指向一維數(shù)組a的第一個(gè)元素a[0],則p+1使p指向下一個(gè)元素a[1],p+i使p指向元素a[i]。

例如,定義

inta[5],*p;

p=a;

inta[5],*p;

p=&a[0];

后,可通過(guò)指針引用數(shù)組元素,如圖7-9所示。圖7-9通過(guò)指向數(shù)組首元素的指針變量引用一維數(shù)組元素

2)指向一維數(shù)組非首元素的指針

現(xiàn)假設(shè)指針p指向數(shù)組a的第三個(gè)元素a[2],則p+1使p指向下一個(gè)元素a[3],p-1使p指向上一個(gè)元素a[1]。

例如,定義

inta[5],*p;

p=&a[2];

后,可通過(guò)指針引用數(shù)組元素,如圖7-10所示。

圖7-10通過(guò)指向數(shù)組非首元素的指針變量引用一維數(shù)組元素

例7-7將字符數(shù)組str2中的字符串復(fù)制到字符數(shù)組str1中。

解題思路①令指針指向字符串str2的首地址;

②將當(dāng)前地址內(nèi)容送入字符數(shù)組str1對(duì)應(yīng)地址單元;

③字符串str2地址+1;

④重復(fù)②、③步驟,直到整個(gè)字符串復(fù)制完畢為止。

根據(jù)上文介紹的知識(shí),用指針指向數(shù)組元素后,訪(fǎng)問(wèn)某個(gè)數(shù)組元素時(shí)有四種方法,因此可以寫(xiě)出四種實(shí)現(xiàn)代碼。

方法一:用數(shù)組名和下標(biāo)來(lái)訪(fǎng)問(wèn)數(shù)組元素。

方法二:用指針名和下標(biāo)來(lái)訪(fǎng)問(wèn)數(shù)組元素。

方法三:用指針名加偏移量計(jì)算出的地址來(lái)訪(fǎng)問(wèn)數(shù)組元素。

方法四:用數(shù)組名加偏移量計(jì)算出的地址來(lái)訪(fǎng)問(wèn)數(shù)組元素。

使用指針訪(fǎng)問(wèn)數(shù)組元素時(shí)應(yīng)注意以下幾點(diǎn)。

(1)若指針p指向數(shù)組a首元素,雖然p+i與a+i意義相同,但并不意味著p就是a。p與a的區(qū)別如下:

①a代表數(shù)組的首地址,是不能改變的。例如

for(p=a;a<(p+10);a++)

printf("%d",*a);

語(yǔ)句企圖通過(guò)a++來(lái)改變a的值是不行的。

②p是一個(gè)指針變量,可指向數(shù)組中的任何元素,p++是符合規(guī)范的,但要注意指針變量的當(dāng)前值。

例7-8利用指向數(shù)組元素的指針輸出數(shù)組a的各個(gè)元素。

(2)使用指針時(shí),應(yīng)盡量避免出現(xiàn)指針訪(fǎng)問(wèn)越界的情況。如例7-8中的for循環(huán)執(zhí)行后,p已經(jīng)越過(guò)數(shù)組的范圍了,如圖7-11所示,這時(shí)它所指向的內(nèi)存單元的值是不確定的,但編譯器不能發(fā)現(xiàn)該問(wèn)題。將例7-8中的程序進(jìn)行如下修改,指針p就不會(huì)越界。圖7-11指針訪(fǎng)問(wèn)越界示例

例7-9定義一個(gè)有10個(gè)元素的數(shù)組a,從鍵盤(pán)輸入10個(gè)數(shù),并以數(shù)組的不同引用形式輸入輸出數(shù)組各元素。

方法一:用下標(biāo)直接訪(fǎng)問(wèn)數(shù)組。

方法二:用指針變量和指針運(yùn)算符訪(fǎng)問(wèn)數(shù)組。

方法三:用數(shù)組名表示的地址輸入輸出數(shù)組各元素。

方法四:用指針表示的下標(biāo)輸入輸出數(shù)組各元素。

方法五:用指向數(shù)組的指針變量移動(dòng)實(shí)現(xiàn)對(duì)數(shù)組的訪(fǎng)問(wèn)。

3.通過(guò)指針引用二維數(shù)組元素

當(dāng)指針p指向二維數(shù)組中的某個(gè)元素時(shí),可以用指針p訪(fǎng)問(wèn)二維數(shù)組的所有元素。

當(dāng)p指向二維數(shù)組的首元素時(shí),p+1將指向數(shù)組第二個(gè)元素,p+2將指向數(shù)組第三個(gè)元素,依次類(lèi)推。例如,定義

inta[2][5];

int*p=&a[0][0];

后,p指向二維數(shù)組a的首元素,如圖7-12所示(指針變量p采用簡(jiǎn)化畫(huà)法)。若將數(shù)組元素用p表示,則二維數(shù)組元素如圖7-13所示。圖7-12通過(guò)指向數(shù)組首元素的指針變量引用二維數(shù)組元素圖7-13用指針變量p表示的二維數(shù)組元素

觀察圖7-12和圖7-13可知,a[i][j]的地址為p+i?×?5+j,a[i][j]可表示為“*(p+i*5+j)”,由此推出如下一般性結(jié)論:

假設(shè)指針變量p已經(jīng)指向共有M行N列的數(shù)組A的首元素,則A[i][j]的地址為p+i?×?N+j,A[i][j]可表示為“*(p+i*N+j)”,其中0≤i<M,0≤j<N。

4.指向數(shù)組首元素的指針變量的運(yùn)算

無(wú)論數(shù)組a是一維數(shù)組還是二維數(shù)組,若指針變量p指向數(shù)組a的首元素,則都存在以下一些常見(jiàn)的運(yùn)算(以下各圖以一維數(shù)組為例)。

1)?p++(或p+=1)

p++表示p指向下一個(gè)元素。示例如圖7-14所示。圖7-14p++執(zhí)行前后指針的變化情況

2)?*p++

因?yàn)椤?”運(yùn)算符和“++”運(yùn)算符同優(yōu)先級(jí),且結(jié)合方向?yàn)椤白杂抑磷蟆?右結(jié)合性),即*p++相當(dāng)于*(p++),而“++”在指針變量p的后面,屬于后置運(yùn)算,出現(xiàn)在表達(dá)式中時(shí)遵循“先用后加”的使用規(guī)則,所以圖7-15所示的示例中,執(zhí)行X=*p++相當(dāng)于執(zhí)行X=*(p++),分解操作相當(dāng)于先執(zhí)行X=(*p),再執(zhí)行p++。

3)?*(p++)與*(++p)

(1)?*(p++):同*p++。示例如圖7-15所示。圖7-15X=*p++執(zhí)行前后各變量的變化情況

(2)?*(++p):由于“++”在指針變量p的前面,屬于前置運(yùn)算,出現(xiàn)在表達(dá)式中時(shí)遵循“先加后用”的使用規(guī)則,所以在圖7-16所示的示例中,執(zhí)行X=*(++p)相當(dāng)于先執(zhí)行++p,再執(zhí)行X=(*p)。圖7-16X=*(++p)執(zhí)行前后各變量的變化情況

4)?(*p)++

由于(*p)++表示p指向的元素值加1,相當(dāng)于(a[0])++,所以在圖7-17所示的示例中,執(zhí)行X=(*p)++相當(dāng)于執(zhí)行X=(a[0])++,分解操作相當(dāng)于先執(zhí)行X=a[0],再執(zhí)行a[0]++。圖7-17X=(*p)++執(zhí)行前后各變量的變化情況

此外,如果p當(dāng)前指向數(shù)組a的非首元素a[i],則

(1)*(p--)相當(dāng)于a[i--],即先取*p,再使p減1。示例如圖7-18和圖7-19所示。

(2)*(++p)相當(dāng)于a[++i],即先使p加1,再取*p。示例如圖7-18和圖7-20所示。

(3)*(--p)相當(dāng)于a[--i],即先使p減1,再取*p。示例如圖7-18和圖7-21所示。圖7-18p指向數(shù)組a的非首元素圖7-19執(zhí)行X=*(p--)后

圖7-20執(zhí)行X=*(++p)后圖7-21執(zhí)行X=*(--p)后

7.2.2指向數(shù)組的指針

指向數(shù)組的指針和指向數(shù)組元素的指針是兩個(gè)不同的概念。在介紹指向數(shù)組的指針之前,先回顧一下指向數(shù)組元素的指針,以免混淆概念。

前面已經(jīng)介紹過(guò),一維和二維數(shù)組在內(nèi)存中都是按行連續(xù)存放的,所以當(dāng)用一個(gè)指針變量指向一維或二維數(shù)組的首元素后,利用該指針變量就可以訪(fǎng)問(wèn)數(shù)組中的任意一個(gè)元素。

例如,定義

inta[4]={80,81,82,83};

int*p=a

inta[4]={80,81,82,83};

int*p=&a[0];

后,可通過(guò)指針引用各個(gè)數(shù)組元素,如圖7-22所示。依次輸出各元素的語(yǔ)句可寫(xiě)為

for(i=0;i<4;i++)

printf("%3d",*(p+i));

圖7-22利用指向一維數(shù)組首元素的指針訪(fǎng)問(wèn)各元素

又如,定義

inta[2][4]={{80,81,82,83},{84,85,86,87}};

int*p=&a[0][0];

后,可通過(guò)指針引用各個(gè)數(shù)組元素,如圖7-23所示。依次輸出各元素的語(yǔ)句可寫(xiě)為

for(i=0;i<8;i++)

printf("%3d",*(p+i));

圖7-23利用指向二維數(shù)組首元素的指針訪(fǎng)問(wèn)各元素

1.指向一維數(shù)組的指針變量的定義與引用

指向一維數(shù)組的指針變量的定義格式為

類(lèi)型說(shuō)明符(*指針變量名)[一維數(shù)組長(zhǎng)度][=初值];

此定義表示定義了一個(gè)指向一維數(shù)組的指針變量,所指向的數(shù)組的元素類(lèi)型由“類(lèi)型說(shuō)明符”說(shuō)明,所指向的數(shù)組的元素個(gè)數(shù)由“一維數(shù)組長(zhǎng)度”說(shuō)明。初值通常是所指數(shù)組的首地址。由于按這種格式定義的指向一維數(shù)組的指針相當(dāng)于是一個(gè)二級(jí)指針,考慮賦值類(lèi)型相容,初值通常賦值為“&一維數(shù)組名”或“二維數(shù)組名”。

例如,定義

inta[4]={80,81,82,83};

int(*p)[4]=&a;

inta[4]={80,81,82,83};

int(*p)[4];

p=&a;

后,內(nèi)存狀態(tài)如圖7-24所示。依次輸出各元素的語(yǔ)句可寫(xiě)為

for(i=0;i<4;i++)

printf("%3d",*(*p+i));

圖7-24利用指向一維數(shù)組的指針訪(fǎng)問(wèn)一維數(shù)組各元素

例7-12結(jié)合圖7-24,分析下面程序的運(yùn)行結(jié)果。

(1)?&a[0]與a是針對(duì)數(shù)組首元素a[0]而言的。&a[0]是取數(shù)組首元素a[0]的地址;a的值是&a[0],也表示數(shù)組首元素a[0]的地址。

(2)?&a與p是針對(duì)整個(gè)數(shù)組a而言的。&a是取整個(gè)數(shù)組a的首地址。p的值是&a,也表示整個(gè)數(shù)組a的首地址。從另一個(gè)方面來(lái)看,p是指向數(shù)組的指針,p自然是存放數(shù)組的首地址。而數(shù)組首元素a[0]與數(shù)組a的首地址是相同的,自然p、&a、a、&a[0]這4個(gè)地址值是相同的。

2.用指向一維數(shù)組的指針指向二維數(shù)組的首行

在二維數(shù)組中,每一行都可以看成一個(gè)一維數(shù)組,因此可以定義一個(gè)指向一維數(shù)組的指針(所指一維數(shù)組長(zhǎng)度等于二維數(shù)組列數(shù)),然后通過(guò)初始化或賦值使它指向二維數(shù)組的首行,接著可以通過(guò)這個(gè)指針訪(fǎng)問(wèn)二維數(shù)組中任何一行,繼而能訪(fǎng)問(wèn)數(shù)組中的任意一個(gè)元素。

使指向一維數(shù)組的指針變量指向二維數(shù)組首行的方法有如下兩種。

(1)初始化。使用類(lèi)型說(shuō)明符,將指針變量定義為指向具有指定長(zhǎng)度的一維數(shù)組,并初始化為二維數(shù)組的首地址。例如:

類(lèi)型說(shuō)明符(*指針變量名)[長(zhǎng)度]=二維數(shù)組的首地址;

(2)賦值。先定義指向一維數(shù)組的指針變量,再將其賦值為二維數(shù)組的首地址。例如:

指向一維數(shù)組的指針變量?=?二維數(shù)組的首地址;

由于按上述格式定義的指向一維數(shù)組的指針相當(dāng)于一個(gè)二級(jí)指針,考慮賦值類(lèi)型相容,二維數(shù)組的首地址可表示為“二維數(shù)組名”或“&一維數(shù)組名”。

例如,定義

inta[2][4]={{80,81,82,83},{84,85,86,87}};

int(*p)[4]=a; //或?qū)懗桑篿nt

(*p)[4]=&a[0];

后,內(nèi)存狀態(tài)如圖7-25所示。依次輸出各元素的語(yǔ)句可寫(xiě)為

for(i=0;i<2;i++)

for(j=0;j<4;j++)

printf("%3d",*(*(p+i)+j));圖7-25利用指向一維數(shù)組的指針訪(fǎng)問(wèn)二維數(shù)組各元素

當(dāng)用一個(gè)指向一維數(shù)組的指針p指向二維數(shù)組a的首行時(shí),數(shù)組元素a[i][j]可以表示為a[i][j]、*(a[i]+j)、*(*(a+i)+j)、*(p[i]+j)、*(*(p+i)+j),數(shù)組元素a[i][j]的地址可以表示為&a[i][j]、a[i]+j、*(a+i)+j、p[i]+j、*(p+i)+j。

例7-13結(jié)合圖7-25,分析下面程序的運(yùn)行結(jié)果。

對(duì)于上面的運(yùn)行結(jié)果,不同機(jī)器上運(yùn)行所得的地址值可能不一樣。但我們應(yīng)重點(diǎn)觀察哪些值是相同的。

(1)?a、p、*p、a[0]、&a[0]、&a[0][0]都是地址,且地址值是相同的,為數(shù)組第一行的首地址。

①a是二維數(shù)組名,代表數(shù)組的首地址。

②a[0]是一維數(shù)組名,代表第一行的首地址。

③&a[0][0]是取數(shù)組首元素的地址。

④&a[0]是取數(shù)組首行的地址,而首行的地址就是首元素的地址。

⑤p是指向一維數(shù)組a[0](二維數(shù)組第一行)的,自然存放a[0]首地址。

⑥*p代表p指向的數(shù)組,即a[0]。

(2)?p+1、*(p+1)、a[1]、&a[1]、&a[1][0]都是地址,且地址值是相同的,為數(shù)組第二行的首地址,分析同上。

(3)?**p、a[0][0]都指數(shù)組第一行首元素的值。

(4)?**(p+1)、a[1][0]都指數(shù)組第二行首元素的值。

例7-14從鍵盤(pán)輸入一個(gè)M行N列的二維整型數(shù)組,然后求取各行的最大值及其列號(hào)并輸出。

7.2.3指針數(shù)組

1.指針數(shù)組的定義

前面介紹了指向不同類(lèi)型變量的指針的定義和使用。我們可以讓指針指向一維、二維數(shù)組或字符數(shù)組,以替代這些數(shù)組在程序中的使用。我們稱(chēng)這樣的指針為數(shù)組指針。

定義多個(gè)同類(lèi)型的指針時(shí),可以仿照數(shù)組的定義形式,這樣數(shù)組元素全是指針,它們分別用于指向某類(lèi)的變量,以替代這些變量在程序中的使用。這樣的數(shù)組稱(chēng)為指針數(shù)組。

指針數(shù)組也是一種數(shù)組,只是數(shù)組中的每個(gè)元素都是“指針”而已,只能用來(lái)存放地址。

指針數(shù)組的定義、賦初值、數(shù)組元素的引用與賦值等操作和一般數(shù)組的處理方法基本相同。需要注意的是,指針數(shù)組的數(shù)組元素是指針類(lèi)型的,對(duì)其元素所賦的值必須是地址值。

指針數(shù)組的定義格式為

類(lèi)型說(shuō)明符*指針數(shù)組名[長(zhǎng)度]={初值};

其中,數(shù)組的每個(gè)元素都是一個(gè)一級(jí)指針,每個(gè)目標(biāo)類(lèi)型由“類(lèi)型說(shuō)明符”指定,元素個(gè)數(shù)由“長(zhǎng)度”指定。此外,還可以在定義的同時(shí)給指針數(shù)組元素賦初值。

例如:

inta=10,b=20,c=30;

int*p[3]={&a,&b,&c};

定義了一個(gè)名為p的指針數(shù)組,其3個(gè)元素p[0]、p[1]、p[2]分別指向3個(gè)整型變量a、b、c,如圖7-26所示。

圖7-26指針數(shù)組元素指向普通int型變量

2.指針數(shù)組的引用

指針數(shù)組元素的引用方法和普通數(shù)組元素的引用方法完全相同,可以利用它來(lái)引用所指向的普通變量或數(shù)組元素,可以對(duì)其賦值,也可以參加運(yùn)算。

例7-16輸入5個(gè)字符串,將這5個(gè)字符串按從小到大的順序排列后輸出。要求用二維字符數(shù)組存放這5個(gè)字符串,用指針數(shù)組元素分別指向這5個(gè)字符串。

解題思路本例處理的是字符串,需要用到字符串處理函數(shù)中的字符串輸入、字符串輸出、字符串比較等庫(kù)函數(shù)。采用的排序方法是“選擇法”。

首先,利用指針數(shù)組將后面的4個(gè)字符串依次與第1個(gè)字符串作比較,若比第1個(gè)字符串小,則交換指針。完成后,第1個(gè)指針數(shù)組元素將指向最小的字符串。

然后,利用指針數(shù)組將后面的3個(gè)字符串依次與第2個(gè)字符串作比較,若比第2個(gè)字符串小,則交換指針。完成后,第2個(gè)指針數(shù)組元素將指向次小的字符串。

同理,使第3個(gè)指針數(shù)組元素指向第3小的字符串,直到把5個(gè)字符串都排好為止。

這5個(gè)字符串排序前后的狀態(tài)如圖7-27所示。圖7-275個(gè)字符串排序前后的狀態(tài)

例7-17利用指針數(shù)組輸出程序菜單。

例7-18利用指針函數(shù),實(shí)現(xiàn)輸入整數(shù)1~7,輸出對(duì)應(yīng)的星期名稱(chēng)。

3.指針數(shù)組作為main()函數(shù)的形參

指針數(shù)組的一個(gè)重要應(yīng)用是作為main()函數(shù)的形參。在以往的程序中,main()函數(shù)的第一行一般寫(xiě)成以下形式:

intmain()

括號(hào)中是空的。實(shí)際上,main()函數(shù)首部的括號(hào)中是可以帶參數(shù)的,而且參數(shù)主要采用“指針數(shù)組”。

在運(yùn)行程序的命令行中,有時(shí)可以在命令名后接一些參數(shù),形如:

命令名參數(shù)1參數(shù)2…參數(shù)n

例如,某同學(xué)編寫(xiě)了一個(gè)將兩個(gè)字符串連接起來(lái)的C程序strlink.c,要求兩個(gè)字符串在運(yùn)行相應(yīng)的可執(zhí)行程序文件strlink.exe時(shí)作為參數(shù)接在命令名strlink的后面,如:

c:\tc>strlinkFirst_stringSecond_string

為了將上述“First_string”“Second_string”連接起來(lái),要在源程序strlink.c中,通過(guò)main()函數(shù)使用的參數(shù)來(lái)說(shuō)明命令行的參數(shù)。main()函數(shù)的參數(shù)定義形式為

intmain(intargc,char*argv[])

其中,argc表示命令行參數(shù)的個(gè)數(shù)(包括命令名),指針數(shù)組argv用于存放參數(shù)(包括命令名)。例如,在命令行“strlinkFirst_stringSecond_string”中相應(yīng)的指針數(shù)組存儲(chǔ)如圖7-28所示,各個(gè)參數(shù)的值如下:

argc=3;

argv[0]="strlink.exe"

argv[1]="First_string"

argv[2]="Second_string"

圖7-28指針數(shù)組用作命令行參數(shù)

例7-19用帶參數(shù)的main()函數(shù)實(shí)現(xiàn)兩個(gè)字符串的連接。

例7-19中的程序要想直接調(diào)試運(yùn)行,可在Debug的對(duì)話(huà)框的Programarguments項(xiàng)中填入?yún)?shù)“First_stringSecond_string”,然后運(yùn)行,即可得到與上面相同的結(jié)果。

例7-20利用指針數(shù)組作main()函數(shù)的主函數(shù)的參數(shù)。

7.2.4指針與字符串

存放在數(shù)組中的字符串處理方法與一維數(shù)組的處理方法基本一致,可以先定義一個(gè)字符類(lèi)型的指針變量,通過(guò)賦初值或賦值的方式讓指針變量指向字符數(shù)組的首元素,然后使用這個(gè)指針變量處理單個(gè)字符,也可以用它一次性地處理整個(gè)字符串。此種方法,這里不再詳細(xì)討論。

1.使指針變量指向字符串的方法

將字符類(lèi)型的指針變量指向字符串有以下兩種方法:

(1)在定義的同時(shí)給指針變量賦初值。例如:

char*p="Goldmedal";

(2)給指針變量賦值。例如:

char*p;

p="Goldmedal";

上述兩種方法,實(shí)際上都是把字符串的首字符G的地址賦給指針變量p,如圖7-29所示。圖7-29指向字符串的指針變量

例7-21給指針變量賦初值。

C語(yǔ)言對(duì)字符串常量是按字符數(shù)組處理的,在內(nèi)存中開(kāi)辟了一個(gè)字符數(shù)組用來(lái)存放字符串常量(包括字符串結(jié)束符?'\0')。注意:程序在定義字符指針變量p時(shí)只是把字符串“Goldmedal”的首地址賦給p,而不是把“Goldmedal”整個(gè)字符串內(nèi)容賦給p。為了讓讀者更清楚這一概念,我們把例7-21的程序進(jìn)行修改,如例7-22所示。

例7-22對(duì)例7-21的程序進(jìn)行修改,以輸出字符串。

例7-21和例7-22的輸出結(jié)果都是

Goldmedal

從例7-22修改后的程序可以看出,指針變量p在定義時(shí)的確只是獲得字符串“Goldmedal”的首地址,而字符串各字符的輸出是靠指針的不斷向后移動(dòng)來(lái)實(shí)現(xiàn)的。

2.指向字符串常量的指針變量的使用

(1)把字符串當(dāng)作整體來(lái)處理。這種方式通常用在字符串的輸入和輸出中。

輸入字符串的格式如下:

scanf("%s",指針變量);

gets(指針變量);

這兩個(gè)函數(shù)使用上有區(qū)別:前者用空白符分隔數(shù)據(jù)(不含空白符);后者按行方式讀入數(shù)據(jù)(含空白符)。

輸出字符串的格式如下:

printf("%s",指針變量);

puts(指針變量);

(2)處理字符串中的單個(gè)字符。

若指針變量已經(jīng)指向了字符串常量,則用指針變量表示的第i個(gè)字符為

*(指針變量+i)

例7-23利用指針變量輸出字符串并統(tǒng)計(jì)字符串的長(zhǎng)度。

例7-24用指針數(shù)組的各指針指向字符串?dāng)?shù)組。

例7-25兩個(gè)字符串的交換。

3.字符指針變量與字符數(shù)組的區(qū)別

用字符數(shù)組和字符指針變量都可實(shí)現(xiàn)字符串的存儲(chǔ)和運(yùn)算,但兩者是有區(qū)別的,在使用時(shí)應(yīng)注意以下幾點(diǎn):

(1)存儲(chǔ)內(nèi)容不同。

字符指針變量本身是一個(gè)變量,用于存放字符串的首地址。而字符串本身是存放在以該首地址為首的一塊連續(xù)的內(nèi)存空間中并以'\0'作為結(jié)束符。字符數(shù)組是由若干個(gè)數(shù)組元素組成的,每個(gè)元素中放一個(gè)字符。

(2)賦值方式不同。

對(duì)字符指針變量,可采用以下方法賦值,如:

char*p;

p="Goldmedal";

而對(duì)字符數(shù)組,只能對(duì)各個(gè)元素逐個(gè)賦值。不能用以下方法對(duì)字符數(shù)組賦值:

charp[20];

p="Goldmedal";

(3)指針變量的值是可以改變的,而數(shù)組名是不允許通過(guò)賦值而改變其值的。

例7-26改變指針變量的值。

從例7-26可知,指針變量p的值是可以變化的,輸出字符串時(shí)從p當(dāng)時(shí)所指向的單元開(kāi)始輸出各個(gè)字符,直至遇到?'\0'?為止。而數(shù)組一旦定義就會(huì)被分配一塊存儲(chǔ)區(qū),這塊存儲(chǔ)區(qū)的首地址(即數(shù)組的首地址)在數(shù)組的生存期內(nèi)是不會(huì)變化的,因此,作為能代表數(shù)組首地址的數(shù)組名,顯然不能通過(guò)被賦值而改變其值。例如:

charp[]="Goldmedal";

p=p+5;

printf("%s",p);

是錯(cuò)誤的。

(4)輸入字符串時(shí)有區(qū)別。如果定義了一個(gè)字符數(shù)組,則在編譯時(shí)為它分配內(nèi)存單元,它有確定的地址。因此,下面的語(yǔ)句是可以的:

charp[10];

scanf("%s",p);

而對(duì)于字符指針變量,下面的語(yǔ)句是不宜采用的:

char*p;

scanf("%s",p);

實(shí)際編程中,應(yīng)采用下面的語(yǔ)句使p指向確定的存儲(chǔ)區(qū):

7.3指針和函數(shù)

7.3.1指針作函數(shù)的參數(shù)

指針可以作為參數(shù)在調(diào)用函數(shù)和被調(diào)用函數(shù)之間傳遞數(shù)據(jù)。它傳遞的是“地址值”。

1.函數(shù)形參為指針,實(shí)參為地址表達(dá)式因?yàn)榈刂繁磉_(dá)式的值是一個(gè)地址值,所以函數(shù)調(diào)用時(shí),實(shí)參地址表達(dá)式傳遞給形參指針變量的值是地址,故參數(shù)傳遞后實(shí)參與對(duì)應(yīng)的形參指向同一個(gè)單元,函數(shù)體內(nèi)對(duì)形參的任何操作就相當(dāng)于是對(duì)實(shí)參的操作。

由于函數(shù)的形參p和q是指針變量,實(shí)參是a和b的地址,參數(shù)傳遞是將a和b的地址傳遞給指針變量p和q,相當(dāng)于執(zhí)行“p=&a;q=&b;”則*p和a,*q和b分別代表同一個(gè)內(nèi)存單元的值,swap()函數(shù)調(diào)用結(jié)束后,*p和*q的值進(jìn)行了交換,就相當(dāng)于a和b的值進(jìn)行了交換,如圖7-30所示(圖中的地址值是假設(shè)的)。

圖7-30利用指針作為函數(shù)參數(shù)實(shí)現(xiàn)兩數(shù)的交換

2.函數(shù)形參為指針,實(shí)參為數(shù)組名

由于數(shù)組名代表的是數(shù)組的首地址,所以數(shù)組名作為實(shí)參傳遞給函數(shù)形參的也是一個(gè)地址值。

例7-27用函數(shù)調(diào)用方式,實(shí)現(xiàn)字符串的復(fù)制。

在本例中,當(dāng)主程序中的調(diào)用函數(shù)string_copy()執(zhí)行時(shí),實(shí)參str1(數(shù)組名)傳遞給形參source(指針變量)的是數(shù)組首地址,因而str1和source指向同一個(gè)單元。同理,str2和dest也指向同一個(gè)單元,如圖7-31所示。

圖7-31例7-27執(zhí)行后的結(jié)果

語(yǔ)句“for(;(*(dest+i)=*(source+i))!='\0';i++);”的執(zhí)行過(guò)程為:首先將源字符串中的當(dāng)前字符復(fù)制到目標(biāo)字符串中;然后判斷該字符(即賦值表達(dá)式的值)是否為結(jié)束符?'\0'。如果不是,則相對(duì)位置變量i的值增1,以便復(fù)制下一個(gè)字符,如果是結(jié)束符?'\0',則結(jié)束循環(huán)。該語(yǔ)句的特點(diǎn)是:先復(fù)制、后判斷,循環(huán)結(jié)束前,結(jié)束符已經(jīng)復(fù)制。

在C語(yǔ)言中,用賦值表達(dá)式,而不是賦值語(yǔ)句來(lái)實(shí)現(xiàn)賦值操作,能給某些處理帶來(lái)很大的靈活性,該語(yǔ)句(實(shí)現(xiàn)字符串的復(fù)制)的用法就是最好的例證。

3.函數(shù)形參為指針變量,實(shí)參也為指針變量

函數(shù)調(diào)用時(shí),實(shí)參指針變量傳遞給形參指針變量的值仍是“地址”,故參數(shù)傳遞后實(shí)參與形參指針變量指向同一個(gè)內(nèi)存單元,函數(shù)體內(nèi)對(duì)形參的任何操作就相當(dāng)于是對(duì)實(shí)參的操作。

例7-28用函數(shù)調(diào)用方式,求字符串的長(zhǎng)度。

例7-29輸入3個(gè)整數(shù)a、b、c,按由大到小的順序?qū)⑺鼈冚敵觥?用函數(shù)實(shí)現(xiàn))

7.3.2返回指針值的函數(shù)

一個(gè)函數(shù)可以返回一個(gè)int型、float型、char型的數(shù)據(jù),也可以返回一個(gè)指針類(lèi)型的數(shù)據(jù)(即地址)。返回指針值的函數(shù)(簡(jiǎn)稱(chēng)指針函數(shù))的定義格式如下:

函數(shù)類(lèi)型*函數(shù)名([形參表])

例如:

int*max(intx,inty);

就定義了一個(gè)函數(shù)名為max的函數(shù),其返回值為指針類(lèi)型,且是指向int型數(shù)據(jù)的指針。而

intmax(intx,inty);

是前面介紹的一種常規(guī)函數(shù)定義,它表示定義了一個(gè)函數(shù)名為max的函數(shù),其返回值為int類(lèi)型。

由此可見(jiàn),返回值為指針的函數(shù)和前面學(xué)習(xí)的返回值為int(或float或char)型的普通函數(shù)在定義上是沒(méi)有根本區(qū)別的,只是“返回值的類(lèi)型”不同而已。

例7-30編一指針函數(shù)求一字符串的子串,并返回子串的首地址。

例7-31輸入一行字符,統(tǒng)計(jì)其中分別有多少個(gè)單詞和空格。比如輸入Howareyou,有3個(gè)單詞和兩個(gè)空格。

例7-32有a個(gè)學(xué)生,每個(gè)學(xué)生有b門(mén)課程的成績(jī)。要求在用戶(hù)輸入學(xué)生序號(hào)以后,輸出該學(xué)生的全部成績(jī)。(用指針函數(shù)來(lái)實(shí)現(xiàn))

7.3.3函數(shù)指針

由前文可知,C語(yǔ)言中的指針,既可以指向(普通)變量(如整型、字符型、實(shí)型等),也可以指向數(shù)組元素或數(shù)組。下面介紹一種指向函數(shù)的指針變量——函數(shù)指針。

在程序運(yùn)行時(shí),函數(shù)代碼是程序的算法指令部分,它

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論