版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、 )掌握指針的基本概念、指針變量的定義、引用 與運(yùn)算;)熟悉指向指針的指針;)掌握指針與數(shù)組、指針與函數(shù)的相關(guān)操作。要求:第6章 指針和引用 學(xué)習(xí)C語言, 如果你不能用指針編寫有效、正確而靈活的程序, 可以認(rèn)為你沒有學(xué)好C語言。地址、指針、數(shù)組及其相互關(guān)系是C語言中最具特色的部分。規(guī)范地使用指針, 可以使程序更加簡(jiǎn)潔明了, 因此, 我們要學(xué)會(huì)在各種情況下正確地使用指針。(1)利用指針能間接引用它所指的對(duì)象。(2)指針能用來描述數(shù)據(jù)和數(shù)據(jù)之間的關(guān)系, 以便構(gòu)造復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。(3)利用各種類型指針形參,能使函數(shù)增加活力。(4)指針與數(shù)組結(jié)合,使引用數(shù)組元素的形式 更加多樣、訪問數(shù)組元素的手段更加
2、靈活。(5)熟練正確應(yīng)用指針能寫特別緊湊高效的程序。指針在C程序中的作用地址和指針的概念內(nèi)存按字節(jié)編址,每個(gè)字節(jié)單元都有一個(gè)地址。程序中定義的任何變量,在編譯時(shí)都會(huì)在內(nèi)存中分配一個(gè)確定的地址單元。我們?cè)鯓又罊C(jī)器將某種數(shù)據(jù)放在內(nèi)存的什么地方呢?可用求地址運(yùn)算符&,例如定義了:int a = 10 ;則&a就代表變量a在內(nèi)存中的地址。因?yàn)榈刂愤\(yùn)算符&就是取其后變量a的地址。可以用 printf(%xn , &a); 看其地址。注意,這個(gè)地址并不是始終不變的,這是由系統(tǒng)來安排的,我們無法預(yù)先知道。以后我們所講的地址都是假設(shè)的.6.1 指針基本概念C語言規(guī)定:如果變量占用連續(xù)的多個(gè)字節(jié),則第一個(gè)字節(jié)
3、的地址就是該變量的地址。例如定義:shorta=10;floatb=10;則編譯系統(tǒng)給變量分配的內(nèi)存空間如圖6.1所示。從圖6.1中可以看出,假設(shè)變量a的內(nèi)存地址為2000,則變量b的內(nèi)存地址為2002。 程序在引用變量時(shí),首先獲得該變量的地址,這還只是變量的首地址,然后還要根據(jù)變量的數(shù)據(jù)類型決定要從首地址開始連續(xù)取幾個(gè)字節(jié)來獲取變量的值。若定義如圖6.1,現(xiàn)程序要獲取變量b的值,則先確定變量首地址為2002,然后由變量b的數(shù)據(jù)類型float知變量占4個(gè)字節(jié),所以從首地址開始連續(xù)取4個(gè)字節(jié)的數(shù)據(jù)即為變量b的值。圖6.1變量分配的內(nèi)存示意short 型變量a占2個(gè)字節(jié)單元float 型變量b占4
4、個(gè)字節(jié)單元 指針與變量這里:a,b是變量,而p是指針變量,存放的是地址20002010abp變量地址內(nèi)存變量名圖6.2變量a與指針變量p的關(guān)系200020028000使用一個(gè)變量可以直接通過變量名,這種方式稱為直接存取方式。還可以將變量的地址存入另一“特殊”變量中,然后就可以通過該“特殊”變量來存取變量的值,這種存取變量的方式稱為“間接存取方式”。而存放地址的變量就好像存放了一個(gè)指針,指向要存取值的變量,故稱為“指針變量”??煞Q為“指向變量的指針變量”。 short a=10,b=20,*p=&a; 指針變量也是變量,在使用之前必須先定義。定義時(shí)也可對(duì)其賦初值。指針變量的定義格式為:存儲(chǔ)類型
5、類型說明符 *pointer=初值; 表示定義了一個(gè)存放某種類型為類型說明符的變量地址的變量,稱為pointer。其中,pointer是指針變量的名字,并且必須由字符*作為指針的前導(dǎo)。 由于指針的存儲(chǔ)單元是用來存放地址的,該地址必定是某個(gè)存儲(chǔ)單元的地址。稱指針指向該存儲(chǔ)單元,并且把指針?biāo)赶虻拇鎯?chǔ)單元稱為指針的目標(biāo)(對(duì)象,object)。簡(jiǎn)而之,指針變量是專門用來存放變量地址的. 指針變量的定義例如:short i; /定義整型變量i short *ip ; /定義整型指針 short *p;/定義整型指向指針的指針變量pip=&i;如果變量i是指針ip的目標(biāo),稱指針ip指向變量i,簡(jiǎn)稱ip指
6、向i。我們用帶箭頭的直線從指針ip指向其目標(biāo)i(如圖)。指針ip 圖6.3. 指針變量與它所指變量關(guān)系圖變量iFF10FF10指針ip的值為變量i的地址FF105箭頭表明指針ip指向?qū)ο骾稱變量i是指針ip的對(duì)象假設(shè):變量i的地址為FF10 在定義指針變量時(shí),應(yīng)注意以下幾點(diǎn):(1)類型說明符表示該指針變量所指向的變量的數(shù)據(jù)類型。如int、float、double、char等。(2)定義指針變量時(shí),指針變量名前必須有一個(gè)“*”號(hào), 表示定義的變量是指針變量,否則就變成了普通整型變量。 double c,*p;(3)指針變量在定義時(shí)允許對(duì)其賦初值。如:double c,*p=&c; /令指針p初始
7、化為變量c的地址需要特別指出的是:這里是用&c對(duì)p初始化, 而不是對(duì)*p初始化。初始化后指針變量p中存放的是實(shí)型變量c的地址。 給指針變量賦值(1) 指針變量名=&變量名;作用: 使指針指向一個(gè)對(duì)象。通過求地址運(yùn)算符(&)把一個(gè)變量的地址賦給指針變量?!?”是求地址運(yùn)算符,該運(yùn)算符為單目運(yùn)算符,用于求變量的地址,且該變量必須為內(nèi)存變量。例如: int a=8,b,*pa,pb; pa=&a; pb=&b;a=8; -直接訪問整型變量a指針變量pa.20008000800280012001200282000 2000*pa=8; -間接訪問pa中存放的是整型變量a的地址圖6.4指針變量名變量&a
8、8paa&bpbb 當(dāng)一個(gè)指針(如 pa)獲得某個(gè)變量(如a)的地址時(shí),我們稱這個(gè)指針指向該變量,即使該變量成為指針的對(duì)象。假設(shè)變量 a 的地址為2000,則當(dāng)pa 指向a 后,pa 的值就等于2000。 也可以在定義指針變量的同時(shí)賦初值,例如: inta=8 ,*p=&a; 和前面表述的一樣,這里是用&a對(duì)p初始化, 而不是對(duì)*p初始化。初始化后指針變量p中存放的是整型變量a的地址。 另外,讀者一定還記得在前面調(diào)用scanf函數(shù)時(shí),其函數(shù)調(diào)用格式中,輸入數(shù)據(jù)所對(duì)應(yīng)的各變量名之前都必須加運(yùn)算符& ,這就是我們所說的求地址運(yùn)算符。scanf函數(shù)把從終端讀入的數(shù)據(jù)依次放入這些地址所代表的存儲(chǔ)單元中
9、,也就是說scanf函數(shù)要求輸入項(xiàng)是地址值。因此接上例,scanf(“%d%d”,&a,&b) ; 語句和scanf(“%d%d” , pa,pb); 語句是等價(jià)的,都是將終端輸入的整型數(shù)據(jù)存入到變量a和變量b所在的存儲(chǔ)單元中。(2) 同類型指針變量之間可以直接賦值。 可以把指針變量的值賦給指針變量,但一定要確保這兩個(gè)指針變量的類型是相同的。 2000102000指針變量p變量a指針變量q2000(&a)例如:float x; int a=10,*p,*q; p=&a; /*方式1*/ q=p; /*方式2*/執(zhí)行以上語句后,使指針變量q也存放了變量a的地址,也就是說指針變量p和q同時(shí)指向了變
10、量a。如執(zhí)行 p=&x ; 語句,則是絕對(duì)錯(cuò)誤的。為什么?請(qǐng)讀者想一想!(3) 給指針變量賦“空”值 為了使指針變量有一確定的數(shù)值,除了給指針變量賦一地址值外,當(dāng)指針變量沒有指向的對(duì)象時(shí),也可以給指針變量賦NULL值,此值為空值。例如:int *p ; p=NULL ; NULL指針p 表示指針變量p為空指針,暫不指向任何變量。 對(duì)于靜態(tài)或全局的指針變量,如果在定義時(shí)未給它指定初值,系統(tǒng)自動(dòng)給它指定初值為0,讓它暫時(shí)是一個(gè)空指針。使指針的值等于零(或者等于空),稱為指針清零。NULL是在stdio.h頭文件中定義的預(yù)定義符,因此在使用NULL時(shí),應(yīng)該在程序的前面出現(xiàn)預(yù)定義命令行:#includ
11、e “stdio.h”。NULL的代碼值為0,所以語句p=NULL ;等價(jià)于:p=0 ; 都是表示指針變量p是一個(gè)空指針,沒有指向任何對(duì)象。給指針變量賦值舉例: int i = 100, j, *ip, *intpt; float f, *fp; 以下都是不正確的賦值 ip = 100; /* 指針變量不能賦整數(shù)值*/ intpt = j;/*指針變量不能賦整型變量的值*/ fp = &i;/能指向float型變量,不能指向int型變量 fp = ip;/不同類型指針變量不能相互賦值 即一個(gè)指針變量只能指向同一個(gè)類型的變量。因?yàn)?,定義什么樣的類型指針變量,該指針變量只能存放什么樣類型變量的地址
12、,兩者必須一致,否則就可能出現(xiàn)了張冠李戴的錯(cuò)誤現(xiàn)象。而以下都是正確的賦值:ip = &i ; /* 使ip指向i */intpt = ip ; /使intpt指向ip所指變量 同類型的指針變量可以相互賦值;fp = &f ; /*使fp指向f*/ip = NULL ;/使ip不再指向任何變量i的地址ipi的值iintpti的地址圖6.5指針變量引用 當(dāng)指針變量中存放了一個(gè)確切的地址值時(shí),通過指針可以用“間接運(yùn)算符”(*)來引用該地址所代表的存儲(chǔ)單元。即利用指針變量,提供對(duì)變量的一種間接訪問形式。(1) 通過指針或地址引用一個(gè)存儲(chǔ)單元 在賦值號(hào)右邊由“*”運(yùn)算符和指針變量組成的表達(dá)式,代表指針?biāo)?/p>
13、指存儲(chǔ)單元的內(nèi)容。如代碼:int i=8,j,*ip ; ip = &i; j = *ip; 第二條語句是把變量i的地址賦給了指針變量ip,第三條語句是把指針變量ip所指向的變量i存儲(chǔ)單元的值8賦給變量j。上述賦值等價(jià)于: j = i;“*”號(hào)在這里是一個(gè)“間接運(yùn)算符”,它為單目運(yùn)算符,與運(yùn)算對(duì)象自右至左結(jié)合,且運(yùn)算對(duì)象必須為一個(gè)地址對(duì)象。例如: j=*&i ; 該語句中“&”運(yùn)算符求出變量i的地址,“*”運(yùn)算符取變量i地址中的值8賦給變量j。例如: int *p , k=0 ; p=&k ; *p=150 ;以上第三條語句是把整數(shù)150存入變量k中。 *p=*p +1 ; 或 *p+=1 ;
14、 以上語句是獲取指針變量p所指向的存儲(chǔ)單元k中的值150,然后加1再放入指針變量p所指向的存儲(chǔ)單元k中,此時(shí)變量k中存放的數(shù)值為151。(b)在賦值號(hào)左邊由“*”和指針變量組成的 表達(dá)式,代表指針?biāo)傅拇鎯?chǔ)單元【例6.1】說明指針變量與它所指變量之間關(guān)系的示意程序#include int main() int k; /一個(gè)整型變量 int *kPtr; /一個(gè)整型指針變量 k = 7; kPtr = &k;/使kPtr指向變量k。 printf(k的地址是 %xnkPtr的值是 %x,&k, kPtr); printf(nk的值是 %dn*kPtr的值是 %d, k ,*kPtr); prin
15、tf(n以下表明運(yùn)算符*和&是互逆的n&*kPtr = %xn*&kPtr = %xn,&*kPtr,*&kPtr); return 0;k的地址是 12ff7ckPtr的值是 12ff7ck的值是 7*kPtr的值是 7以下表明運(yùn)算符 * 和 & 是互逆的:&*kPtr = 12ff7c*&kPtr = 12ff7c輸出結(jié)果:kPtr&kk7記住對(duì)變量的兩種訪問方式:圖6.620008地址: 8000 (&p)2000(&a)指針變量p變量aa或*p的值都為8對(duì)變量的兩種訪問方式:直接訪問:按變量地址存取變量值間接訪問:通過存放變量地址的變量去訪問變量(1)當(dāng)定義局部指針變量時(shí),如果未給它指
16、定初值,則它的值是不確定的。程序在使用它們時(shí),應(yīng)首先給它們賦值,讓指針變量確定指向某個(gè)變量。例如: short *pa; 表示只是定義了一個(gè)指針,它還沒有對(duì)象。 例如:printf(%dn, *pa);表示訪問非法,將是致命的錯(cuò)誤,也是初學(xué)者易犯的錯(cuò)誤。為正確理解和使用指針變量,必須注意以下幾點(diǎn):以下語句正確:short a=3, *pa=&a; *pa = a + 6; /a=a+6(2) 指針變量只能取變量的地址值 不能將任何其他非地址值賦給指針變量。例如:int i, *ip = &i; /ip= i; *ip = i; 通過某個(gè)指向變量i的指針變量ip間接引用變量i與直接按變量名i引用
17、變量i,效果是相同的,凡能直接按變量名可引用的地方,也可以用指向它的某個(gè)指針變量間接引用它。例如,有,則凡變量i能使用的地方,*ip一樣能用。(3)單目運(yùn)算符*、&、+和-是從右向左結(jié)合的。注意分清運(yùn)算對(duì)象是指針變量、還是指針變量所指對(duì)象。例如,有變量定義 int i=200, j, *ip = &i ;代碼 j = +*ip;/j=? 先是*ip,間接引用ip所指向的變量(變量i),然后對(duì)變量i的自增運(yùn)算,并將運(yùn)算結(jié)果賦值給變量j。 +*ip,+(*ip) 表示ip指向的元素值加1。ip+,ip+=1; ip指向下一個(gè)元素。*ip+, *(ip+) 先取*ip,再使ip加1。*ip- ,*(
18、ip-) 先取*ip,再使ip減1。*(-ip) ; 先使ip減1,再取*ip。*(+ip); 先使ip加1,再取*ip。 由于”+”在指針變量ip的前面,屬于前置運(yùn)算,出現(xiàn)在表達(dá)式中時(shí)遵循“先加后用”的使用規(guī)則.例如: j = *ip+; 或 j=*(ip+); 因?yàn)椤?”運(yùn)算符和“+”運(yùn)算符同優(yōu)先級(jí),而結(jié)合方向?yàn)椤白杂抑磷蟆保ㄓ医Y(jié)合性),即它相當(dāng)于*(ip+)。而“+”在指針變量ip的后面,屬于后置運(yùn)算,出現(xiàn)在表達(dá)式中時(shí)遵循“先用后加”的使用規(guī)則. 即表達(dá)式*ip+的值與*ip相同,并在求出表達(dá)式值的同時(shí),ip增加了1個(gè)單位。相當(dāng)于代碼 j = *ip; ip+;經(jīng)上述表達(dá)式計(jì)算后,ip不
19、再指向變量j。 這種情況常用在指針指向數(shù)組元素的情況,在引用數(shù)組某元素之后,自動(dòng)指向數(shù)組的下一個(gè)元素。代碼 j = (*ip)+ ;則是先間接引用ip所指向的變量,取這個(gè)變量的值賦值給j,并讓該變量自增。指針變量的引用小結(jié)&a表示變量a的地址;假設(shè)&a的地址為:2000,a=8;p指針變量p的值,p=&a*p表示指針變量p指向的變量*p=a=8*&a相當(dāng)于*(&a),有*(&a)*pa=8&*p相當(dāng)于&(*p),有&*p=&(*p)=&a=2000&p表示指針變量p的地址,若有&p=8000*&p相當(dāng)于*(&p),有*(&p)=2000&*a寫法有誤,因* 后只能接指針變量假設(shè): int a=
20、8,*p=&a;6.2 指向數(shù)組元素的指針數(shù)組在內(nèi)存中占用連續(xù)的存儲(chǔ)空間,數(shù)組名代表的是數(shù)組的首地址??啥x一個(gè)指針變量,通過賦值或函數(shù)調(diào)用參數(shù)傳遞的方式,把數(shù)組名或數(shù)組的第1個(gè)元素的地址賦值給該指針變量,該指針變量就指向了該數(shù)組首元素。當(dāng)一個(gè)指針指向數(shù)組首元素后,對(duì)數(shù)組所有元素的訪問,既可以使用數(shù)組下標(biāo),也可以使用指針。7654321pq例如:int a7, *p,*q; p=a;表示:把a(bǔ)0元素的地址賦給指針變量p,即p是指向數(shù)組a的首地址。 q = &a3 ;表示:把a(bǔ)1元素的地址賦給指針變量 p,即p是指向數(shù)組a的下標(biāo)為3的元素的指針。好處:1.為引用數(shù)組元素提供了一種新的途徑;2.比
21、用下標(biāo)引用數(shù)組元素更靈活和簡(jiǎn)潔,因?yàn)橹羔樣幸欢ǖ倪\(yùn)算能力。#include void main() short a=1,2,3,4,5,6,7; short n,*p; /*p=&a0; n=sizeof(a)/sizeof(a0); for(p=a;pa+n;p+) printf(%4d,*p); printf(n);例如:12345672000200220042006200820102012p執(zhí)行p+后pp循環(huán)結(jié)束使用指針時(shí),應(yīng)盡量避免指針訪問越界。在上例循環(huán)執(zhí)行后,p已經(jīng)越過數(shù)組的范圍,如圖所示,這時(shí)它所指向的單元的值是不確定的,但編譯器不能發(fā)現(xiàn)該問題,避免指針訪問越界是程序員自己的責(zé)任
22、。 在定義的同時(shí)為指針變量賦初值例1:inta10;int*p = &a0; int*q = &a8; 例2:int b25;int *p=&b00; int *q=&b13; 圖6.7對(duì)指向數(shù)組元素的指針允許作有限的運(yùn)算:例如: int *p, *q, a10; p = &a1; q = &a5;(1)當(dāng)兩個(gè)指針指向同一個(gè)數(shù)組的元素時(shí),這兩個(gè)指針可以作關(guān)系比較( , =, != )。若 p=q 表示p,q指向數(shù)組的同一個(gè)元素; pq 表示p所指向的數(shù)組元素的下標(biāo)大于q所指向的數(shù)組元素的下標(biāo)。 若兩個(gè)指針要做減法運(yùn)算,要求這兩個(gè)指針必須指向同一個(gè)數(shù)組,運(yùn)算的結(jié)果是它們所指向數(shù)組元素下標(biāo)相差的整
23、數(shù).p-q; 結(jié)果為整數(shù)-4q-p; 結(jié)果為整數(shù)4pq(2) 指向數(shù)組元素的指針可與整數(shù)進(jìn)行加減運(yùn)算,使指針指針指向在數(shù)組元素之間前后移動(dòng) 由于數(shù)組元素在內(nèi)存中順序連續(xù)存放,數(shù)組名代表的是數(shù)組的首地址。因此表達(dá)式a+1為a1的地址,a+2為a2的地址。 當(dāng)用一個(gè)指針指向數(shù)組首元素后,對(duì)數(shù)組所有元素的訪問,既可以使用數(shù)組下標(biāo),也可以使用指針. 若指針 p = &a0; 則表達(dá)式 p+n 的值為 an的地址。或者說,p+n的值為指向an的指針值。注意: 在使用指針過程中,通過移動(dòng)指針(p)來實(shí)現(xiàn)對(duì)不同數(shù)據(jù)單元的訪問操作。 p+1不是將p的值和1簡(jiǎn)單地相加。對(duì)不同的類型,移動(dòng)的單位長(zhǎng)度不同。單位長(zhǎng)度
24、一般是指針?biāo)赶虻淖兞康臄?shù)據(jù)類型長(zhǎng)度。 如果數(shù)組元素是短整型(short),p+1表示p的地址加2;如果數(shù)組元素是實(shí)型(float),或整型(int) ,p+1表示p的地址加4;如果數(shù)組元素是字符型,p+1表示p的地址加1。(3) 引用數(shù)組元素的方法(1)當(dāng)指針變量p指向一維數(shù)組a的第一個(gè)元素a0 ,如p=&a0;數(shù)組的第i+1個(gè)數(shù)組元素ai有如下寫法:下標(biāo)法,如ai數(shù)組名,如 *(a+i)表示ai。指針變量,如 *(p+i),或pi。 圖6.8同理:ai的地址也對(duì)應(yīng)有如下寫法: &ai , &pi, a+i , (p+i)例如: int a100, b100, *p, *q; for(p=a
25、;pa+100;)scanf(%d,p+);/*利用指針遍歷數(shù)組,輸入數(shù)組的全部元素*/ for(p=a;p=&a99;p+) printf(*p = %dt, *p);/*利用指針遍歷數(shù)組,輸出數(shù)組的全部元素*/ printf(n); for(p=a,q=b;pa+100;)*q+=*p+;/* 利用指針將已知數(shù)組復(fù)制到另一個(gè)數(shù)組*/ (2) 指向一維數(shù)組非首元素的指針假設(shè)指針p指向一維數(shù)組a的第3個(gè)元素a2,則:如右圖所示。p1: 使p指向下一個(gè)元素a3。(p+1)p-1: 使p指向前一個(gè)元素a1。(p-1)同理:pi: 使p指向元素a2+i。(p+i)d) p-i:使p指向元素a2-i
26、(p-i)由上可知:當(dāng)指針變量p指向一維數(shù)組a的第n個(gè)元素an以后,數(shù)組的第i個(gè)數(shù)組元素ai有如下寫法:ai ,pni,*(a+i),*(p+ni)如:p=&a4;則pi引用的是a4+i,則: p-2,引用的是a2.圖6.9 在實(shí)際應(yīng)用中,一般是定義指向一維數(shù)組“首元素”的指針來對(duì)數(shù)組進(jìn)行操作。同理:ai的地址也對(duì)應(yīng)有如下寫法: &ai , &pni, a+i , (p+ni)再次提醒注意:定義指向數(shù)組元素的指針變量,其指針類型應(yīng)與數(shù)組元素類型相同。例如定義:floata10; int*p = &a0; 中的第二個(gè)語句就是錯(cuò)誤的,因?yàn)槎x的指針p是一個(gè)整型指針,它是指向整型數(shù)據(jù)的,而數(shù)組元素是
27、實(shí)型數(shù)據(jù),類型不相同。所以使用時(shí)千萬要小心哦。用數(shù)組名與指針的區(qū)別:使用指針訪問數(shù)組元素,應(yīng)注意的問題是: 若指針p指向數(shù)組a首元素,雖然p+i與a+i、*(p+i)與*(a+i)意義相同,但仍應(yīng)注意p與a的區(qū)別。 a代表數(shù)組的首地址,是常量,不變的,例如語句for(p=a; a(p+10); a+) printf(%d, *a);企圖通過語句a+來改變a的值是不合法的。 p是一個(gè)指針變量,可指向數(shù)組中的任何元素,例如p+,故要注意指針變量的當(dāng)前值。 通過指針引用二維數(shù)組元素舉例 當(dāng)p指向二維數(shù)組的首元素后,p+1將指向數(shù)組第2個(gè)元素,p+2將指向數(shù)組第3個(gè)元素,依此類推。例如定義:int a
28、25;int *p=&a00;后,p指向二維數(shù)組a的首元素,如圖6.10所示。若將數(shù)組元素用p表示出來,則如圖6.11所示。a00a01a02a03a03a10a11a12a13a13*p*(p+1)*(p+2)*(p+3)*(p+4)*(p+5)*(p+6)*(p+7)*(p+8)*(p+9)圖6.11用指針變量p表示的二維數(shù)組元素pp+1p+2p+3p+4p+5p+6p+7p+8p+9圖6.10對(duì)圖進(jìn)行觀察,可知:aij的地址為p+i*5+j,aij可表示為*(p+i*5+j)。由此推出一般性的結(jié)論如下:假設(shè)指針變量p已經(jīng)指向共有M行N列的數(shù)組A的首元素,則 aij的地址為p+i*N+j,
29、 aij可表示為*(p+i*N+j)。 其中 0iM(行數(shù)), 0jN(列數(shù))。ij程序清單如下:#include #define M 2#define N 4void main() int aMN, max, i, j; int *p=&a00;/*通過賦初值使p指向a數(shù)組首元素*/ printf(請(qǐng)輸入數(shù)組中各元素的值:n);for(i=0;iM;i+) for(j=0;jN;j+)scanf(%d,p+);/*通過p+依次引用各數(shù)組元素地址*/例:用指針法求二維數(shù)組的最大值。max=a00;/*首先認(rèn)為第一元素的值是最大值*/p=&a00; /*通過賦值使p指向a數(shù)組首元素*/for(i
30、=0;iM;i+) for(j=0;jN;j+) if(max*(p+i*N+j) /*max與各數(shù)組元素進(jìn)行比較*/ max=*(p+i*N+j);/*max總是存放比較后的大者*/printf(數(shù)組中的最大值為:%dn,max);/*輸出最大值*/* 12 3 45 6 8 100 56 78*/指針與字符串 當(dāng)字符串存放在數(shù)組中,其處理方法與一維數(shù)組的處理方法基本一致,可以先定義一個(gè)字符類型的指針變量,通過賦初值或賦值的方式讓指針變量指向字符數(shù)組首元素。然后就可以使用這個(gè)指針變量處理單個(gè)字符,也可以用它一次性地處理整個(gè)字符串,此種方法不再詳細(xì)討論。本節(jié)主要討論利用字符類型的指針變量處理字
31、符串常量的方法。 void main() char *string=I love China! ; printf(%sn,string); (2) 給指針變量賦值。例如: char *string; string=I love China! ;IloveChina!0string將字符類型的指針變量指向字符串有兩種方法:(1) 在定義的同時(shí)給指針變量賦初值。例如: 上述兩種方式,實(shí)際上都是把字符串的第一個(gè)字符string的地址賦給指針變量1.使指針變量指向字符串的方法 2指向字符串常量的指針變量的使用(1) 把字符串當(dāng)作整體來處理這種方式通常用在字符串的的輸入和輸出中,格式如下:1. 輸入字符
32、串:(a) scanf(%s,指針變量);(b) gets(指針變量);2. 輸出字符串:(a) printf(%s,指針變量);(b) puts(指針變量);(2) 處理字符串中的單個(gè)字符若指針變量已經(jīng)指向了字符串常量,則用指針變量表示的第i個(gè)字符為:*(指針變量+i)3.使用字符指針變量與字符數(shù)組的區(qū)別(1) 存儲(chǔ)內(nèi)容不同。 字符指針變量本身是一個(gè)變量,用于存放字符串的首地址。而字符串本身是存放在以該首地址為首的一塊連續(xù)的內(nèi)存空間中并以0作為串的結(jié)束。字符數(shù)組是由若干個(gè)數(shù)組元素組成的,每個(gè)元素中放一個(gè)字符。(2) 賦值方式不同。對(duì)字符指針變量,可采用下面方法賦值:如:char *s;s=I
33、 love China! ; 而對(duì)字符數(shù)組只能對(duì)各個(gè)元素逐個(gè)賦值,不能用以下辦法對(duì)字符數(shù)組賦值:char s20;s=I love China! ; (3) 指針變量的值可以改變;而數(shù)組名代表的是該數(shù)組的首地址,是常量,它的值是不能改變的。例#include void main() char *p=Gold medal; p=p+5; printf(%s,p);例#include void main() char a=Gold medal; a=a+5; printf(%s,a);(4) 內(nèi)存分配有區(qū)別:如果定義了一個(gè)字符數(shù)組,在編譯時(shí)自動(dòng)為它分配內(nèi)存單元,它有確定的地址。指針在定義時(shí),若沒有
34、人為的給它分配內(nèi)存或使它指向確定的內(nèi)存單元,則該指針指向的內(nèi)存位置是不確定的。(這點(diǎn)也是初學(xué)者常犯的錯(cuò)誤,請(qǐng)通過后面的課深入掌握)#include void main()char p10;scanf(%s,p);printf(%s, p);#include void main()char *p;scanf(%s,p);printf(%s, p);? 前面說過,當(dāng)一個(gè)指針變量在未取得確定地址前使用是危險(xiǎn)的,容易引起錯(cuò)誤。但是對(duì)指針變量直接賦值是可以的。因?yàn)镃系統(tǒng)對(duì)指針變量賦值時(shí)要給以確定的地址。因此, char *cp1, *cp2 = I am a string;/*用字符串常量初始化字符指針
35、變量或者*/cp1 = Another string; /*用字符串常量賦值給字符指針變量*/都是合法的。 使字符指針變量cp2指向字符串常量 I am a string的第一個(gè)字符I,使cp1指向字符串常量Another string 的第一個(gè)字符A。以后就可通過cp2或cp1分別訪問這兩個(gè)字符串常量中的其它字符。例如,*cp2或cp20就是I,*(cp1+3)或cp13就是字符t。 要特別強(qiáng)調(diào)指出,企圖通過指針變量修改存于常量區(qū)中的字符串常量是不允許的。例如: 將cp20中I改成y,將會(huì)出現(xiàn)致命的錯(cuò)誤.例如,調(diào)用庫函數(shù)strlen()求字符串常量的長(zhǎng)度: strlen(I am a str
36、ing.)該函數(shù)調(diào)用的結(jié)果是14,表示這個(gè)字符串常量由14個(gè)有效字符組成。如果s是一個(gè)字符數(shù)組,其中已存有字符串,cp是一個(gè)字符指針變量,它指向某個(gè)字符串的首字符:char s = I am a string., *cp = Another string.;則代碼: printf(%sn,s);輸出存于字符數(shù)組s中的字符串。而代碼: printf(%sn,cp);輸出字符指針變量cp所指向的字符串。 【例6.2】字符串復(fù)制:實(shí)現(xiàn)將字符數(shù)組s2中的字符串復(fù)制到字符數(shù)組s1中。 根據(jù)前面介紹的知識(shí),用指針指向數(shù)組元素后,訪問某個(gè)數(shù)組元素時(shí)有四種方法,我們因此可以寫出四種實(shí)現(xiàn)代碼。#include
37、void main( )int i=0;char s120,s220=How are you!;for(;(s1i=s2i) !=0;i+);puts(s1);(1)用數(shù)組名下標(biāo)來訪問數(shù)組元素。 由于字符串結(jié)束符0的值為0,上述測(cè)試當(dāng)前復(fù)制字符是不是字符串結(jié)束符的代碼中,“!=0”是多余的,字符串復(fù)制更簡(jiǎn)潔的寫法是: for(;s1i=s2i;i+);也可用:while(s1i=s2i)i+;(2)用指針移位或指針名下標(biāo)來訪問數(shù)組元素。#include void main( )int i=0;char s120,s220=How are you!;char *from=s2,*to=s1; w
38、hile(*to+=*from+); /*whie(toi=fromi)i+;指針名接下標(biāo)*/puts(s1); (3)用指針名加偏移量計(jì)算出的地址來訪問數(shù)組元素#include void main( )int i=0;char s120,s220=How are you!;char *to=s1,*from=s2;while(*(to+i)=*(from+i)i+;puts(s1);(4)用數(shù)組名加偏移量計(jì)算出的地址來訪問數(shù)組元素#include void main( )int i=0;char s120,s220=How are you!;while(*(s1+i)=*(s2+i)i+;p
39、uts(s1);【例6.3】將字符串s中的某個(gè)字符去掉,假設(shè)要去掉的字符與字符變量c中的字符相同。 可以采用邊考察字符,邊復(fù)制不同字符來實(shí)現(xiàn)。現(xiàn)引入字符指針p和q,其中p指向當(dāng)前正要考察的字符,若它所指的字符與c中的字符不同,則將它復(fù)制到新字符串中。否則,該字符不被復(fù)制,即從新的字符串中去掉了;q指向下一個(gè)用于存儲(chǔ)復(fù)制字符的存儲(chǔ)位置。每次復(fù)制一個(gè)字符后,q增加1。每次考察了一個(gè)字符后,p就增1。 for(p = q = s; *p; p+) if (*p != c) *q+ = *p; /* 復(fù)制 */ *q = 0; /* 重新構(gòu)成字符串 */6.3指針與函數(shù)指針與函數(shù)的結(jié)合使編程更為靈活。指針可以用作函數(shù)的參數(shù)(傳遞地址值)函數(shù)也可以返回一個(gè)指針類型的值,甚至可以定義指向函數(shù)的指針。 1函數(shù)形參為指針,實(shí)參為地址表達(dá)式 因?yàn)榈刂繁磉_(dá)式的值是一個(gè)地址值,所以函數(shù)調(diào)用時(shí),實(shí)參地址表達(dá)式傳遞給形參指針變量的值是地址,故參數(shù)傳遞后實(shí)參與對(duì)應(yīng)的形參指向同一個(gè)單元,函數(shù)體內(nèi)對(duì)形參的任
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 感人的結(jié)婚致辭13篇
- 愚人節(jié)的日記(集錦11篇)
- 護(hù)士臨床能力考核總結(jié)
- 智研咨詢發(fā)布:2024年中國(guó)廢舊動(dòng)力電池梯次利用行業(yè)競(jìng)爭(zhēng)格局及發(fā)展前景研究報(bào)告
- 2024年中國(guó)三網(wǎng)融合行業(yè)市場(chǎng)集中度、市場(chǎng)規(guī)模及未來前景分析報(bào)告
- 無人機(jī)在火災(zāi)防控中的應(yīng)用培訓(xùn)
- 音樂學(xué)校前臺(tái)工作總結(jié)
- 二零二五年個(gè)人果園果樹種植與農(nóng)產(chǎn)品加工合作協(xié)議4篇
- 現(xiàn)代農(nóng)業(yè)產(chǎn)業(yè)園建設(shè)方案
- 能源供應(yīng)服務(wù)招標(biāo)合同三篇
- 第1課 隋朝統(tǒng)一與滅亡 課件(26張)2024-2025學(xué)年部編版七年級(jí)歷史下冊(cè)
- 2025-2030年中國(guó)糖醇市場(chǎng)運(yùn)行狀況及投資前景趨勢(shì)分析報(bào)告
- 【歷史】唐朝建立與“貞觀之治”課件-2024-2025學(xué)年統(tǒng)編版七年級(jí)歷史下冊(cè)
- 冬日暖陽健康守護(hù)
- 產(chǎn)業(yè)園區(qū)招商合作協(xié)議書
- 水處理藥劑采購(gòu)項(xiàng)目技術(shù)方案(技術(shù)方案)
- 2024級(jí)高一上期期中測(cè)試數(shù)學(xué)試題含答案
- 盾構(gòu)標(biāo)準(zhǔn)化施工手冊(cè)
- 天然氣脫硫完整版本
- 山東省2024-2025學(xué)年高三上學(xué)期新高考聯(lián)合質(zhì)量測(cè)評(píng)10月聯(lián)考英語試題
- 不間斷電源UPS知識(shí)培訓(xùn)
評(píng)論
0/150
提交評(píng)論