第9章指針及其應(yīng)用_第1頁(yè)
第9章指針及其應(yīng)用_第2頁(yè)
第9章指針及其應(yīng)用_第3頁(yè)
第9章指針及其應(yīng)用_第4頁(yè)
第9章指針及其應(yīng)用_第5頁(yè)
已閱讀5頁(yè),還剩149頁(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)介

第9章指針及其應(yīng)用鹽城第9章指針及其應(yīng)用9.1指針的引入9.2指針與指針變量9.3指針與數(shù)組9.4指針應(yīng)用與實(shí)例9.1指針的引入9.1.1問(wèn)題與引例前面學(xué)習(xí)了如何使用數(shù)組存放多個(gè)相同類型的數(shù)據(jù)并進(jìn)行運(yùn)算,但數(shù)組的長(zhǎng)度在定義時(shí)必須設(shè)置為確定值,且在程序執(zhí)行過(guò)程中不能改變大小。例如:例6.1中數(shù)組a的長(zhǎng)度是10,程序中只能引用10個(gè)數(shù)組元素a[0]~a[9]。如果事先無(wú)法確定需要處理的數(shù)據(jù)數(shù)量,又應(yīng)該如何解決呢?9.1.1問(wèn)題與引例【引例】編程實(shí)現(xiàn)輸出2到n之間的所有素?cái)?shù)。問(wèn)題分析:

解決此類問(wèn)題可采用聲明一個(gè)數(shù)組并指定數(shù)組長(zhǎng)度的方法,但數(shù)組的長(zhǎng)度在運(yùn)行時(shí)才能知道,通常采用的方法是聲明一個(gè)較大的數(shù)組,使它可以存放可能出現(xiàn)的最多元素。思考:(1)這樣會(huì)不會(huì)造成內(nèi)存空間的浪費(fèi)?

(2)有沒(méi)有更好的方法來(lái)解決這個(gè)問(wèn)題呢?指針是存放內(nèi)存地址的一種變量類型,也就是說(shuō),指針這個(gè)變量是用來(lái)說(shuō)明某個(gè)變量在內(nèi)存中的位置,也可以認(rèn)為指針是指向另一個(gè)變量的變量。指針是C語(yǔ)言的重要特色,也是C語(yǔ)言的精華。9.1.2指針的基本概念指針的主要功能與特點(diǎn):正確靈活地運(yùn)用指針可以有效地表示復(fù)雜的數(shù)據(jù)結(jié)構(gòu),方便地使用數(shù)組和字符串;可以在函數(shù)間進(jìn)行數(shù)據(jù)傳遞;可以直接處理內(nèi)存地址、動(dòng)態(tài)分配內(nèi)存;可以設(shè)計(jì)出結(jié)構(gòu)緊湊、效率更高的應(yīng)用程序。9.1.2指針的基本概念9.2指針與指針變量9.2.1地址與指針9.2.2創(chuàng)建指針9.2.3指針變量賦值9.2.4指針變量運(yùn)算9.2.5指針變量作為函數(shù)參數(shù)9.2.1地址與指針指針是C語(yǔ)言中的一種特殊數(shù)據(jù),用于指明變量、數(shù)據(jù)或函數(shù)在內(nèi)存中存放位置。由于指針的內(nèi)部實(shí)現(xiàn)機(jī)制是通過(guò)地址來(lái)完成的,因此,通俗地講指針就是地址。一個(gè)變量在內(nèi)存中的地址稱為這個(gè)變量的指針。

1.內(nèi)存的地址

程序運(yùn)行時(shí),程序的所有代碼和數(shù)據(jù)都要事先被調(diào)入內(nèi)存,由操作系統(tǒng)為它們分配特定的內(nèi)存空間。

內(nèi)存是以字節(jié)為單位的一片連續(xù)存儲(chǔ)空間,為了便于訪問(wèn),給每個(gè)字節(jié)一個(gè)唯一的編號(hào),這些單元編號(hào)稱為內(nèi)存單元的“地址”。系統(tǒng)的內(nèi)存就像是帶有編號(hào)的小房間,使用內(nèi)存就需要得到房間編號(hào)。變量的數(shù)據(jù)就存放在地址所標(biāo)識(shí)的內(nèi)存單元中,變量中的數(shù)據(jù)其實(shí)就相當(dāng)于倉(cāng)庫(kù)中各個(gè)房間存放的貨物。9.2.1地址與指針1.內(nèi)存的地址系統(tǒng)的內(nèi)存就像是帶有編號(hào)的小房間,使用內(nèi)存就需要得到房間編號(hào)。定義一個(gè)整型變量i,整型變量需要4個(gè)字節(jié),所以編譯器就為變量i分配編號(hào)1000到1003。1000100110021003i01000100110021003i01000pP中存放的是變量i的地址9.2.1地址與指針1.內(nèi)存的地址地址是內(nèi)存區(qū)中對(duì)每個(gè)字節(jié)的編號(hào)。下圖中的1000,1004等就是內(nèi)存單元的地址,而0,1則是內(nèi)存單元的內(nèi)容,也就是說(shuō)基本整型變量i在內(nèi)存中的地址是從1000開(kāi)始的。問(wèn)變量j的地址是什么?01231000100410081012變量i變量j9.2.1地址與指針2.變量的地址一般微機(jī)使用的C語(yǔ)言系統(tǒng)為整型變量分配2個(gè)字節(jié)(C++中整型變量占用4個(gè)字節(jié)),為實(shí)型變量分配4個(gè)字節(jié),為字符型變量分配1個(gè)字節(jié),為雙精度類型變量分配8個(gè)字節(jié)。當(dāng)某一變量被定義后,其內(nèi)存中的地址也就確定了。思考:變量在內(nèi)存中是如何存放的?又是如何使用的呢?9.2.1地址與指針【例9.1】不同類型的變量的存儲(chǔ)形式。#include<stdio.h>voidmain(){inti=5,j=10;//定義整型變量i,j,并賦值為5和10floatx=0.618,y=3.14159;//定義x,y,并賦值為0.618和3.14159charc1='m',c2='N';//定義c1,c2,并賦值為'm'和'N'int*p1,*p2;//定義指向整型變量的指針變量p1,p2p1=&i;p2=&j;//將p1指向i,p2指向jprintf("i=%d,j=%d\n",i,j);printf("x=%f,i=%d\n",x,*p1);}9.2.1地址與指針inti=3,j=6,k;printf(”%d”,i);通過(guò)變量名i找到i的地址2000,從而從存儲(chǔ)單元讀取33.尋址方式有了指針,對(duì)變量訪問(wèn)有直接尋址和間接尋址兩種方式。(1)直接尋址直接尋址是指直接利用變量名進(jìn)行存取的方式。(2)間接尋址間接尋址是將變量的地址存放在另一種類型的變量中,通過(guò)這種新的變量類型來(lái)得到變量的值。9.2.1地址與指針inti=3,j=6,k;k=i+j;從這里取3將9送到這里從這里取6直接存取9inti=3,j=6,k;定義特殊變量i_pointer將i的地址存到這里間接存取i_pointer=&i;*i_pointer=50;509i200032000i_pointer*i_pointer20003直接存取間接存取33inti=3;inti,*i_pointer;i_pointer=&i;*i_pointer=3;*i_pointer表示i_pointer指向的對(duì)象i9.2.1地址與指針4.指針和指針變量指向就是通過(guò)地址來(lái)體現(xiàn)的,一個(gè)變量的地址稱為該變量的“指針”。

例如,地址2000是變量i的指針如果有一個(gè)變量專門用來(lái)存放另一變量的地址(即指針),則它稱為“指針變量”例如:i_pointer就是一個(gè)指針變量。指針變量就是地址變量,用來(lái)存放地址的變量,指針變量的值是地址(即指針)。9.2.1地址與指針注意:“指針”和“指針變量”是不同的概念可以說(shuō)變量i的指針是2000,而不能說(shuō)i的指針變量是2000指針是一個(gè)地址,而指針變量是存放地址的變量。4.指針和指針變量9.2.1地址與指針9.2.2創(chuàng)建指針如果在程序中聲明一個(gè)變量,并使用地址作為該變量的值,那么這個(gè)變量就是指針變量。定義指針變量的一般形式為:

類型說(shuō)明符

*指針變量名;例如:int*pi;

float*pf;

char*pc;基類型指定指針變量可指向的變量類型如pi可以指向整型變量,但不能指向浮點(diǎn)型變量9.2.2創(chuàng)建指針注意:1.定義指針變量要使用指針聲明符“*”;2.定義多個(gè)指針變量時(shí),每一個(gè)指針變量前面都必須加上“*”。3.一個(gè)指針變量只能指向同類型的變量。如:pf只能指向float型變量,不能指向一個(gè)字符變量或整型變量。9.2.3指針變量賦值

指針變量定義后,變量值不確定,引用前必須先賦值,也稱為指針變量的初始化。指針變量賦值時(shí),有三種情況:9.2.3指針變量賦值

1.將變量的地址賦值給指針變量若有如下定義:inta,b,*pa,*pb;a=3;b=5;pa=&a;pb=&b;9.2.3指針變量賦值

2.指針變量間的賦值pa和pb都是整型指針變量,它們之間可相互賦值。例如:pa=&a;pb=pa;pa、pb指向同一個(gè)變量a,pa、pb是等價(jià)的。9.2.3指針變量賦值

3.空指針除了上面介紹的給指針變量賦予確定的地址之外,還可以給指針變量賦空值,該指針不指向任何變量。當(dāng)指針的值為NULL時(shí),稱該指針為空指針。代表空指針的符號(hào)常量NULL在頭文件stdio.h中定義,其值為0,在使用時(shí)應(yīng)加上包含命令。#include<stdio.h>int*p;p=NULL;或p=0;或p=’\0’;9.2.3指針變量賦值

有關(guān)指針的幾種賦值方式:給指針變量賦值。如:p=&a;引用指針變量指向的變量。如有p=&a;*p=1;

則執(zhí)行printf(”%d”,*p);將輸出1引用指針變量的值。如:printf(”%o”,p);使p指向a*p相當(dāng)于a以八進(jìn)制輸出a的地址9.2.3指針變量賦值

下面都是合法的定義和初始化:float*pointer_3;char*pointer_4;inta,b;int*pointer_1=&a,*pointer_2=&b;*pointer_1=&a;錯(cuò)誤pointer_3=&a;錯(cuò)誤pointer_1=&a;正確pointer_3=2000;

錯(cuò)誤9.2.3指針變量賦值

【例9.2】指針變量賦值。#include<stdio.h>//頭文件voidmain()//主函數(shù){inti=2,j;//聲明變量

float*pf;//定義基類型為float的指針變量pfpf=&i;//指針變量賦值

j=*pf;printf("i=%d\tj=%d\n",i,j);//輸出}9.2.4指針變量的運(yùn)算

指針就是地址,指針變量就是變量的地址。指針運(yùn)算的實(shí)質(zhì)就是地址運(yùn)算。指針變量的運(yùn)算主要有:賦值、取地址、取內(nèi)容、加減一個(gè)整數(shù)等運(yùn)算。當(dāng)兩個(gè)指針指向同一數(shù)組時(shí)可以進(jìn)行關(guān)系運(yùn)算。9.2.4指針變量的運(yùn)算

1.指針運(yùn)算符兩個(gè)有關(guān)指針的運(yùn)算符:&和*

(1)&—返回操作數(shù)地址的單目運(yùn)算符。&a是變量a的地址(2)*—指針運(yùn)算符,返回指定地址內(nèi)的變量的值,也是單目運(yùn)算符。運(yùn)算符“*”不僅能從指定內(nèi)存地址取得內(nèi)容,也可以修改指定內(nèi)存地址中的內(nèi)容。9.2.4指針變量的運(yùn)算

1.指針運(yùn)算符注意:指針運(yùn)算符“*”和指針變量說(shuō)明中的指針說(shuō)明符“*”所表達(dá)的意義是不一樣的。在指針變量說(shuō)明中,“*”是類型說(shuō)明符,表示其后的變量是指針類型而表達(dá)式中出現(xiàn)的“*”,則是一個(gè)運(yùn)算符,用來(lái)表示指針變量所指的變量當(dāng)前值。

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

1.指針運(yùn)算符如:inta=6,*p;p=&a;p指向變量a,則*p就代表a。k=*p;(把a(bǔ)的值賦給k)

*p=1;(把1賦給a)【例9.3】指針運(yùn)算符的運(yùn)用。#include<stdio.h>//頭文件voidmain()//主函數(shù){inti;//聲明普通變量int*pi;//聲明指針變量pi=&i;//指針變量賦值i=10;//普通變量i賦初值printf("i=%d\t*pi=%d\n",i,*pi);//輸出變量值及指針?biāo)赶蜃兞康闹?pi=5;//修改指針?biāo)赶虼鎯?chǔ)單元里的值printf("i=%d\t*pi=%d\n",i,*pi}此處*與類型名在一起。此時(shí)共同定義指針變量此處*與指針變量一起使用。此時(shí)代表指針變量所指向的變量程序分析:在上述程序中,首先將變量i地址賦值給指針變量pi。然后,將變量i的值設(shè)置為10,因?yàn)橹羔樧兞縫i是指向變量i的,所以*pi得到的值也將是10。接著,程序中將常量5賦值給指針變量pi所指向的內(nèi)存單元(即變量i),因此變量i的值也隨之改變。*pi和變量i都指向完全相同的內(nèi)存空間,可以互相取代。9.2.4指針變量的運(yùn)算

(2)取地址運(yùn)算符“&”

取地址運(yùn)算符“&”是單目運(yùn)算符,其結(jié)合性為自右至左,其功能是取變量的地址。在程序中,變量的地址是由編譯系統(tǒng)分配的,對(duì)用戶完全透明,用戶不知道變量的具體地址。C語(yǔ)言中提供了地址運(yùn)算符“&”,可以獲取變量的首地址。其一般形式:&變量名

其中:“&”為取地址運(yùn)算符,變量名為預(yù)先聲明的變量。例如,&a表示變量a的首地址,&b表示變量b的首地址。

【例9.4】輸入兩個(gè)整數(shù),按從大到小的順序輸出,不允許交換兩個(gè)數(shù)的位置。解題思路:采用指針?lè)椒▉?lái)處理這個(gè)問(wèn)題。不交換整型變量的值,而是交換兩個(gè)指針變量的值。#include<stdio.h>voidmain(){int*pmax,*pmin,*pt,a,b;printf("integernumbers:");scanf("%d,%d",&a,&b);pmax=&a;pmin=&b;if(*pmax<*pmin){pt=pmax;pmax=pmin;pmin=pt;}printf("a=%d,b=%d\n",a,b);printf("%d,%d\n",*pmax,*pmin);}abpmaxpminpt59&a&b#include<stdio.h>voidmain(){int*pmax,*pmin,*pt,a,b;printf("integernumbers:");scanf("%d,%d",&a,&b);pmax=&a;pmin=&b;if(*pmax<*pmin){pt=pmax;pmax=pmin;pmin=pt;}printf("a=%d,b=%d\n",a,b);printf("%d,%d\n",*pmax,*pmin);}abpmaxpminpt59&a&b&b&a#include<stdio.h>voidmain(){int*pmax,*pmin,*pt,a,b;printf("integernumbers:");scanf("%d,%d",&a,&b);pmax=&a;pmin=&b;if(*pmax<*pmin){pt=pmax;pmax=pmin;pmin=pt;}printf("a=%d,b=%d\n",a,b);printf("%d,%d\n",*pmax,*pmin);}abpmaxpminpt59&a&b&b&a注意:a和b的值并未交換,它們?nèi)员3衷?但pmax和pmin的值改變了。pmax的值原為&a,后來(lái)變成&b,pmin原值為&b,后來(lái)變成&a,這樣在輸出*pmax和*pmin時(shí),實(shí)際上是輸出變量b和a的值,所以先輸出9,然后輸出59.2.4指針變量的運(yùn)算

2.指針變量的運(yùn)算(1)指針的賦值運(yùn)算在引用指針變量前,給指針變量設(shè)置一個(gè)具體的指向,如上例程序中的pmax=&a;pmin=&b;。(2)指針變量與整數(shù)的加減運(yùn)算指針變量除了能進(jìn)行賦值、間接訪問(wèn)(取值)運(yùn)算外,還支持與整數(shù)類型的加減法操作。9.2.4指針變量的運(yùn)算

2.指針變量的運(yùn)算(2)指針變量與整數(shù)的加減運(yùn)算①

指針+1運(yùn)算—該指針指向(物理上的)下一個(gè)存儲(chǔ)單元的首地址。②

指針-1運(yùn)算—與指針+1類似,是指向上一個(gè)存儲(chǔ)單元的首地址。例如:inta[10],*p=a;p是一個(gè)指向數(shù)組a的首元素的指針p+=1則表示指針p指向了數(shù)組元素a[l],

即指向數(shù)組的下一個(gè)元素。9.2.4指針變量的運(yùn)算

2.指針變量的運(yùn)算(3)關(guān)系運(yùn)算具有相同基類型的兩個(gè)指針變量可以進(jìn)行關(guān)系運(yùn)算。例如,假設(shè)p1和p2兩個(gè)指針都指向同一個(gè)數(shù)組的元素,則p1和p2可進(jìn)行下列關(guān)系運(yùn)算:>、>=、<、<=、==、!=。一般來(lái)說(shuō),指針變量的關(guān)系運(yùn)算,只有在這兩個(gè)指針變量指向同一個(gè)數(shù)組時(shí)才有實(shí)際意義。當(dāng)測(cè)試某指針變量是否為空指針時(shí),可以和NULL進(jìn)行比較。9.2.4指針變量的運(yùn)算

(3)關(guān)系運(yùn)算例如,假設(shè)有下列語(yǔ)句:intarr1[10];int*p,*q;p=&arr1[3];q=&arr1[5];則:p==q結(jié)果為“假”,當(dāng)p和q指向相同元素時(shí)為“真”。p<q結(jié)果為“真”,當(dāng)p指向的元素在q指向的元素前面時(shí)為“真”。p>q結(jié)果為“假”,當(dāng)p指向的元素在q指向的元素后面時(shí)為“真”。p!=q結(jié)果為“真”,當(dāng)p和q指向不同元素時(shí)為“真”。p==NULL結(jié)果為“假”,當(dāng)p的值等于NULL時(shí)為“真”。9.2.4指針變量的運(yùn)算

(4)指針變量的相減運(yùn)算具有相同基類型的兩個(gè)指針變量可以進(jìn)行相減運(yùn)算,表示兩個(gè)指針變量所指向的變量之間間隔的基類型的元素個(gè)數(shù)。這種操作,通常當(dāng)這兩個(gè)指針變量指向同一個(gè)數(shù)組時(shí)才有實(shí)際意義。例如,假設(shè)有下列語(yǔ)句:intarr1[10];int*p,*q;p=&arr1[5];q=&arr1[2];printf("%d\n",p-q);9.2.5指針變量作為函數(shù)的參數(shù)通過(guò)前面的學(xué)習(xí)知道整型變量、實(shí)型變量、字符型變量、數(shù)組名和數(shù)組元素等均可作為函數(shù)參數(shù)。此外,指針型變量也可以作為函數(shù)參數(shù)。形參為變量,對(duì)應(yīng)實(shí)參應(yīng)為形參為指針,對(duì)應(yīng)實(shí)參應(yīng)為常量,變量,表達(dá)式,數(shù)組元素地址單向傳遞雙向傳遞9.2.5指針變量作為函數(shù)的參數(shù)【例9.5】將例9.4改為用指針作為函數(shù)參數(shù),輸入兩個(gè)數(shù),按從大到小順序輸出。解題思路:定義一個(gè)函數(shù)swap,將指向兩個(gè)整型變量的指針變量作為實(shí)參傳遞給swap函數(shù)的形參指針變量,在函數(shù)中通過(guò)指針實(shí)現(xiàn)交換兩個(gè)變量的值。#include<stdio.h>voidmain(){voidswap(int*p1,int*p2);inta,b;int*p1,*p2;printf("pleaseenteraandb:");scanf("%d,%d",&a,&b);

p1=&a;p2=&b;

if(a<b)swap(p1,p2);printf("max=%d,min=%d\n",a,b);}abp159&a&bp2voidswap(int*p1,int*p2){inttemp;temp=*p1;*p1=*p2;*p2=temp;}abp159&a&bp2p1&ap2&b95temp5voidswap(int*p1,int*p2){inttemp;temp=*p1;*p1=*p2;*p2=temp;}voidswap(int*p1,int*p2){int*temp;

*temp=*p1;*p1=*p2;*p2=*temp;}錯(cuò)!無(wú)確定的指向#include<stdio.h>voidmain(){……if(a<b)swap(a,b);printf(”max=%d,min=%d\n”,a,b);}voidswap(intx,inty){inttemp;temp=x;x=y;y=temp;}錯(cuò)!無(wú)法交換a,bab59xy5995如果想通過(guò)函數(shù)調(diào)用得到n個(gè)要改變的值:①在主調(diào)函數(shù)中設(shè)n個(gè)變量,用n個(gè)指針變量指向它們。

②設(shè)計(jì)一個(gè)函數(shù),有n個(gè)指針形參。在這個(gè)函數(shù)中改變這n個(gè)形參的值。③在主調(diào)函數(shù)中調(diào)用這個(gè)函數(shù),在調(diào)用時(shí)將這n個(gè)指針變量作實(shí)參,將它們的地址傳給該函數(shù)的形參。

④在執(zhí)行該函數(shù)的過(guò)程中,通過(guò)形參指針變量,改變它們所指向的n個(gè)變量的值。

⑤主調(diào)函數(shù)中就可以使用這些改變了值的變量。注意:函數(shù)的調(diào)用可以(而且只可以)得到一個(gè)返回值(即函數(shù)值),而使用指針變量作參數(shù),可以得到多個(gè)變化了的值。如果不用指針變量是難以做到這一點(diǎn)的。要善于利用指針?lè)ā?.3指針與數(shù)組9.3.1指針與一維數(shù)組9.3.2指針與二維數(shù)組9.3.3指針與字符數(shù)組9.3.4指向指針的指針9.3.5指針數(shù)組與數(shù)組指針9.3.6主函數(shù)main的形參9.3.7指向函數(shù)的指針變量9.3.8指向函數(shù)的指針變量9.3指針與數(shù)組一個(gè)變量有地址,一個(gè)數(shù)組包含若干元素,每個(gè)數(shù)組元素都有相應(yīng)的地址。數(shù)組在內(nèi)存中的存放是一組連續(xù)的存儲(chǔ)單元。數(shù)組名就是數(shù)組在內(nèi)存中存儲(chǔ)的首地址。指針變量用于存放變量的地址,也可以存放數(shù)組的首地址或數(shù)組元素的地址,數(shù)組與指針相互關(guān)聯(lián)。1.定義指向一維數(shù)組的指針inta[10]={1,3,5,7,9,11,13,15,17,19};int*p;p=&a[0];等價(jià)于p=a;等價(jià)于int*p=a;或int*p=&a[0];注意:數(shù)組名a不代表整個(gè)數(shù)組,只代表數(shù)組首元素的地址?!皃=a;”的作用是“把a(bǔ)數(shù)組的首元素的地址賦給指針變量p”,而不是“把數(shù)組a各元素的值賦給p”。9.3.1指針與一維數(shù)組或

p=a;【例9.6】利用指針對(duì)數(shù)組中的每一個(gè)元素進(jìn)行輸入輸出操作。#include<stdio.h>voidmain(){inti,a[5]={5,10,15,20,25};//聲明數(shù)組并初始化

int*p=a;//定義指針并指向一維數(shù)組

for(i=0;i<5;i++)//下標(biāo)法循環(huán)輸出數(shù)組元素

{printf("a[%d]=%d\n",i,a[i]);}printf("\n");for(i=0;i<5;i++)//指針?lè)绞窖h(huán)輸出

{printf("*(p+%d)=%d\n",i,*(p+i));}}9.3.1指針與一維數(shù)組回顧:指針指向數(shù)組元素時(shí),允許以下運(yùn)算:加一個(gè)整數(shù)(用+或+=),如p+2減一個(gè)整數(shù)(用-或-=),如p-2自加運(yùn)算,如p++,++p自減運(yùn)算,如p--,--p兩個(gè)指針相減,如p1-p2(只有p1和p2都指向同一數(shù)組中的元素時(shí)才有意義)9.3.1指針與一維數(shù)組(1)如果指針變量p已指向數(shù)組中的一個(gè)元素,則p+1指向同一數(shù)組中的下一個(gè)元素,p-1指向同一數(shù)組中的上一個(gè)元素。floata[10],*p=a;假設(shè)a[0]的地址為2000,則p的值為2000p+1的值為2004P-1的值為1996(2)如果p的初值為&a[0],則p+i和a+i就是數(shù)組元素a[i]的地址,或者說(shuō),它們指向a數(shù)組序號(hào)為i的元素a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]pp+1,a+1p+i,a+ip+9,a+9(3)*(p+i)或*(a+i)是p+i或a+i所指向的數(shù)組元素,即a[i]。a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]pp+1,a+1p+i,a+ip+9,a+9*(p+i)(4)如果指針p1和p2都指向同一數(shù)組p2-p1的值是4不能進(jìn)行p1+p2運(yùn)算!a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]p1p22.用指針訪問(wèn)數(shù)組元素引用一個(gè)數(shù)組元素,可用下面兩種方法:

(1)下標(biāo)法,如a[i]形式

(2)指針?lè)?,?(a+i)或*(p+i)

其中a是數(shù)組名,p是指向數(shù)組元素的指針變量,其初值p=a9.3.1指針與一維數(shù)組9.3.1指針與一維數(shù)組

【例9.7】

有一個(gè)整型數(shù)組a,有10個(gè)元素,要求輸出數(shù)組中的全部元素。解題思路:引用數(shù)組中各元素的值有3種方法:(1)下標(biāo)法;(2)通過(guò)數(shù)組名計(jì)算數(shù)組元素地址,找出元素的值;(3)用指針變量指向數(shù)組元素分別寫(xiě)出程序,并比較分析。(1)下標(biāo)法

#include<stdio.h>voidmain(){inta[10];inti;printf("enter10integernumbers:\n");for(i=0;i<10;i++)scanf("%d",&a[i]);//一維數(shù)組輸入for(i=0;i<10;i++)printf("%d",a[i]);//一維數(shù)組輸出printf("%\n");}(2)通過(guò)數(shù)組名計(jì)算數(shù)組元素地址,找出元素的值#include<stdio.h>voidmain(){inta[10];inti;printf("enter10integernumbers:\n");for(i=0;i<10;i++)scanf("%d",&a[i]);

for(i=0;i<10;i++)printf("%d",*(a+i));printf("\n");}scanf("%d",a+i);(3)用指針變量指向數(shù)組元素#include<stdio.h>voidmain(){inta[10];int*p,i;printf("enter10integernumbers:\n");for(i=0;i<10;i++)scanf("%d",&a[i]);

for(p=a;p<(a+10);p++)printf("%d",*p);printf("\n");}for(p=a;p<(a+10);p++)scanf("%d",p);for(p=a;p<(a+10);a++)printf("%d",*a);錯(cuò)!3種方法的比較:①第(1)和第(2)種方法執(zhí)行效率相同C編譯系統(tǒng)是將a[i]轉(zhuǎn)換為*(a+i)處理的,即先計(jì)算元素地址。因此用第(1)和第(2)種方法找數(shù)組元素費(fèi)時(shí)較多。②第(3)種方法比第(1)、第(2)種方法快用指針變量直接指向元素,不必每次都重新計(jì)算地址,像p++這樣的自加操作是比較快的這種有規(guī)律地改變地址值(p++)能大大提高執(zhí)行效率3種方法的比較:③用下標(biāo)法比較直觀,能直接知道是第幾個(gè)元素。

用地址法或指針變量的方法不直觀,難以很快地判斷出當(dāng)前處理的是哪一個(gè)元素。9.3.1指針與一維數(shù)組3.用數(shù)組名作函數(shù)參數(shù)

數(shù)組名可以做函數(shù)的形參和實(shí)參。當(dāng)數(shù)組名作為參數(shù)被傳遞時(shí),若形參數(shù)組中各元素發(fā)生了變化,則原實(shí)參數(shù)組各元素的值也隨之變化。

因?yàn)閿?shù)組名作為實(shí)參時(shí),在調(diào)用函數(shù)時(shí)是把數(shù)組的首地址傳送給形參,因此實(shí)參數(shù)組與形參數(shù)組共占一段內(nèi)存單元,采用“地址傳遞”方式,屬于雙向傳遞。

以數(shù)組元素作為實(shí)參時(shí),與使用變量作為實(shí)參一樣的,采用“值傳遞”方式,即使形參數(shù)組元素值發(fā)生了變化,原實(shí)參的數(shù)組元素值也不會(huì)受影響。9.3.1指針與一維數(shù)組3.用數(shù)組名作函數(shù)參數(shù)用數(shù)組名作函數(shù)參數(shù)時(shí),因?yàn)閷?shí)參數(shù)組名代表該數(shù)組首元素的地址,形參應(yīng)該是一個(gè)指針變量。C編譯都是將形參數(shù)組名作為指針變量來(lái)處理的voidmain(){voidfun(intarr[],intn];//函數(shù)聲明intarray[10];

fun(array,10);//函數(shù)調(diào)用

}voidfun(intarr[],intn)//函數(shù)定義{┇}fun(int*arr,intn)voidmain(){voidfun(intarr[],intn];intarray[10];

fun(array,10);}voidfun(int*arr,intn){┇}array[0]arr[0]array數(shù)組arrarray[3]arr[3]arr+3

實(shí)參數(shù)組名是指針常量,但形參數(shù)組名是按指針變量處理在函數(shù)調(diào)用進(jìn)行虛實(shí)結(jié)合后,它的值就是實(shí)參數(shù)組首元素的地址在函數(shù)執(zhí)行期間,形參數(shù)組可以再被賦值voidfun(intarr[],intn){printf(″%d\n″,*arr);

arr=arr+3;

printf(″%d\n″,*arr);

}3、用數(shù)組名作函數(shù)參數(shù)【例9.8】用自定義函數(shù)中形參為指針的方式,求一維數(shù)組的平均值。(1)算法分析首先定義數(shù)組a,并將數(shù)組首地址賦值給指針p。在程序中,通過(guò)函數(shù)調(diào)用,實(shí)現(xiàn)求一維數(shù)組平均值。函數(shù)定義時(shí),定義第一個(gè)形參為指針,第二個(gè)形參為數(shù)組元素的個(gè)數(shù),可使函數(shù)更具有通用性。#include<stdio.h>voidmain(){inti;floata[10],ave,*p;floatpj(float*p1,intn);p=a;//定義指針并指向一維數(shù)組

for(i=0;i<10;i++){scanf("%f",&a[i]);//下標(biāo)法循環(huán)輸入數(shù)組元素

}

ave=pj(p,10);printf("%7.2f\n",ave);}floatpj(float*p1,intn){inti;floatave,s=0;for(i=0;i<n;i++)//指針?lè)绞窖h(huán)輸出

{s=s+*p1; p1++;}ave=s/n;returnave;}

例如:用指針?lè)▽?duì)10個(gè)整數(shù)按由大到小順序排序。解題思路:在主函數(shù)中定義數(shù)組a存放10個(gè)整數(shù),定義int*型指針變量p指向a[0]定義函數(shù)sort使數(shù)組a中的元素按由大到小的順序排列在主函數(shù)中調(diào)用sort函數(shù),用指針p作實(shí)參用選擇法進(jìn)行排序#include<stdio.h>voidmain(){voidsort(intx[],intn);inti,*p,a[10];p=a;for(i=0;i<10;i++)scanf("%d",p++);p=a;sort(p,10);for(p=a,i=0;i<10;i++){printf("%d",*p);p++;}printf("\n");}voidsort(intx[],intn){inti,j,k,t;for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++)if(x[j]>x[k])k=j;if(k!=i) {t=x[i];x[i]=x[k];x[k]=t;}}}voidsort(int*x,intn)if(*(x+j)>*(x+k))k=j;{t=*(x+i);*(x+i)=*(x+k);*(x+k)=t;}9.3.2指針和二維數(shù)組指針變量可以指向一維數(shù)組中的元素,也可以指向多維數(shù)組中的元素。但在概念上和使用方法上,多維數(shù)組的指針比一維數(shù)組的指針要復(fù)雜一些。9.3.2指針和二維數(shù)組1.二維數(shù)組的地址一維數(shù)組在內(nèi)存中的起始地址是數(shù)組的指針,數(shù)組名是一維數(shù)組起始元素的常指針,數(shù)組元素在內(nèi)存中順序存放。二維數(shù)組的表示方法與一維數(shù)組類似,同樣,也可以利用指針?lè)▉?lái)表示二維數(shù)組。可以將二維數(shù)組理解為一個(gè)一維數(shù)組,其數(shù)組元素又是一個(gè)一維數(shù)組。9.3.2指針和二維數(shù)組1.二維數(shù)組的地址inta[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};1357911131517192123a[0]a[1]a[2]aa+1a+2a[0]a[0]+1a[0]+2a[0]+3行指針列指針a代表第0行首地址a+1代表第1行首地址a+2代表第2行首地址1357911131517192123a[0]a[1]a[2]aa+1a+2a[0]a[0]+1a[0]+2a[0]+3行指針列指針行指針每加1,走一行a+i代表行號(hào)為i的行首地址(按行變化)*(a+i)代表什么?1357911131517192123a[0]a[1]a[2]aa+1a+2a[0]a[0]+1a[0]+2a[0]+3行指針列指針相當(dāng)于a[i]a[0]代表a[0][0]的地址a[0]+1代表a[0][1]的地址a[0]+2代表a[0][2]的地址a[0]+3代表a[0][3]的地址1357911131517192123a[0]a[1]a[2]aa+1a+2a[0]a[0]+1a[0]+2a[0]+3行指針列指針列指針每加1,走一列a[1]代表誰(shuí)的地址?a[1]+1代表誰(shuí)的地址?a[1]+2代表誰(shuí)的地址?a[1]+3代表誰(shuí)的地址?1357911131517192123a[0]a[1]a[2]aa+1a+2a[0]a[0]+1a[0]+2a[0]+3行指針列指針a[i]+j代表誰(shuí)的地址?1357911131517192123a[0]a[1]a[2]aa+1a+2a[0]a[0]+1a[0]+2a[0]+3行指針列指針代表a[i][j]的地址*(a[i]+j)代表什么?代表元素a[i][j]*(*(a+i)+j)代表什么?與*(a[i]+j)等價(jià)2.指向二維數(shù)組的指針變量(1)指向數(shù)組元素的指針變量

例如:

有一個(gè)3×4的二維數(shù)組,要求用指向元素的指針變量輸出二維數(shù)組各元素的值。解題思路:二維數(shù)組的元素是整型的,相當(dāng)于整型變量,可以用int*型指針變量指向它二維數(shù)組的元素在內(nèi)存中是按行順序存放的,即存放完序號(hào)為0的行中的全部元素后,接著存放序號(hào)為1的行中的全部元素,依此類推因此可以用一個(gè)指向整型元素的指針變量,依次指向各個(gè)元素#include<stdio.h>voidmain(){inta[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};int*p;for(p=a[0];p<a[0]+12;p++){if((p-a[0])%4==0)printf("\n");printf("%4d",*p);}printf("\n");}控制換行逐個(gè)訪問(wèn)各元素時(shí)常用此類指針(2)指向由m個(gè)元素組成的一維數(shù)組的指針變量

intb[3][4];int(*p)[4];//表示指向由4個(gè)元素組成的一維數(shù)組的指針變量

p=b;

數(shù)組元素b[i][j]可以采用以下六種形式表示:b[i][j]*(b[i]+j)*(*(b+i)+j)p[i][j]*(p[i]+j)*(*(p+i)+j)#include<stdio.h>voidmain(){inti,j;inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};for(i=0;i<3;i++){for(j=0;j<4;j++)

printf("%4d",a[i][j]);//下標(biāo)法 printf("\n");}}【例9.9】輸出二維數(shù)組a中各個(gè)數(shù)組元素的值。方法一:用下標(biāo)法法輸出二維數(shù)組。#include<stdio.h>voidmain(){inti,j,*p;inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

p=&a[0][0];//指向二維數(shù)組的第一個(gè)元素for(i=0;i<3;i++){for(j=0;j<4;j++,p++)

printf("%4d",*p);//p++指向二維數(shù)組中下一個(gè)數(shù)組元素 printf("\n");}}方法二:用指向數(shù)組元素的指針來(lái)實(shí)現(xiàn)#include<stdio.h>voidmain(){inti,j;int[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};int(*p)[4];//定義指向由4個(gè)元素組成的一維數(shù)組的指針pp=a[0];//指向特殊的一維數(shù)組第一個(gè)元素for(i=0;i<3;i++){for(j=0;j<4;j++)

printf("%4d",*(*(p+i)+j));//p+i表示指向i行 printf("\n");

}}方法三:用指向行的指針變量(*p)[4]來(lái)實(shí)現(xiàn)三種方法比較第一種方法是下標(biāo)法,比較直觀,能直接知道是第幾行第幾列元素。將數(shù)組元素a[i][j]轉(zhuǎn)化成*(*(a+i)+j)處理的,即先計(jì)算元素地址,執(zhí)行效率較低。第二種是將指針指向第一個(gè)數(shù)組元素,指針每移動(dòng)一次,按數(shù)組元素在內(nèi)存的存放順序依次處理,一次跳過(guò)一個(gè)數(shù)組元素。第三種方法是采用指向二維數(shù)組行的指針變量方法,指針每移動(dòng)一次,跳過(guò)該行M列元素。后兩種方法用指針變量直接指向數(shù)組元素,而不必每次重新計(jì)算地址,提高了執(zhí)行效率。9.3.3指針和字符數(shù)組字符串是存放在字符數(shù)組中,且以’\0’作為字符串結(jié)束標(biāo)志,數(shù)組名表示該字符串在內(nèi)存中的首地址。當(dāng)定義一個(gè)指針變量指向字符數(shù)組后,就可以通過(guò)指針訪問(wèn)數(shù)組中的每一個(gè)數(shù)組元素。9.3.3指針和字符數(shù)組訪問(wèn)字符串有數(shù)組法和指針?lè)▋煞N方式。1.用字符數(shù)組存放一個(gè)字符串例如:charstr[]="Iamastudent.";printf("%s\n",str);9.3.3指針和字符數(shù)組2.用字符指針指向一個(gè)字符串(1)直接用字符指針指向字符串中的字符例如:char*str="Iamastudent.";//定義str為指針變量,并指向字符串的首地址。printf("%s\n",str);在這里沒(méi)有使用字符數(shù)組,而是定義了一個(gè)字符指針變量str,指向該字符串的首地址。9.3.3指針和字符數(shù)組2.用字符指針指向一個(gè)字符串(2)字符指針指向已定義的字符數(shù)組例如:char*p;charstr[20]={"Iamastudent."};p=str;printf("%s\n",p);也可以直接賦值。例如:charstr[20]={"Iamastudent."},*p=str;9.3.3指針和字符數(shù)組2.用字符指針指向一個(gè)字符串(2)字符指針指向已定義的字符數(shù)組C語(yǔ)言對(duì)字符串常量是按字符數(shù)組進(jìn)行處理的,在內(nèi)存中開(kāi)辟了一個(gè)字符數(shù)組來(lái)存放字符串常量。注意:通過(guò)字符數(shù)組名或字符指針變量可以一次性輸出的只有字符數(shù)組(即字符串),而對(duì)一個(gè)數(shù)值型的數(shù)組,是不能企圖用數(shù)組名輸出它的全部元素的,只能借助于循環(huán)逐個(gè)輸出數(shù)組元素。9.3.3指針和字符數(shù)組3.指向字符串的指針變量操作

當(dāng)定義一個(gè)字符指針變量指向字符串后,通過(guò)該指針變量對(duì)字符串進(jìn)行的操作有兩種方式。(1)對(duì)字符串中的字符進(jìn)行操作

對(duì)字符串中的字符進(jìn)行操作,用“*指針變量名”實(shí)現(xiàn)引用,并通過(guò)指針變量的運(yùn)算實(shí)現(xiàn)移動(dòng),指向不同的字符進(jìn)行處理。

唯一不同的是,判斷一個(gè)字符串的結(jié)束需要通過(guò)判斷“是否遇到字符串的結(jié)束標(biāo)志'\0'”來(lái)實(shí)現(xiàn)。9.3.3指針和字符數(shù)組【例9.10】通過(guò)循環(huán)語(yǔ)句控制,逐個(gè)輸出字符串中的字符。(1)算法分析首先定義字符指針p,并賦以字符串常量"Computer",此時(shí)字符指針存放字符串常量首元素的地址。輸出時(shí),通過(guò)循環(huán)依次輸出字符指針當(dāng)前所指字符,并移動(dòng)指針到下一個(gè)字符,直到遇到字符串結(jié)束標(biāo)志'\0'。9.3.3指針和字符數(shù)組(2)程序設(shè)計(jì)#include<stdio.h>voidmain(){char*p; p="Computer"; while(*p!='\0')//判斷是否為字符串結(jié)束標(biāo)志'\0'{ printf("%c",*p);//輸出字符指針當(dāng)前所指向存儲(chǔ)單元中的字符

p++;//移動(dòng)字符指針到下一個(gè)元素位置

}}9.3.3指針和字符數(shù)組3.指向字符串的指針變量操作(2)對(duì)字符串進(jìn)行整串操作

采用指向字符串或字符數(shù)組的指針名作為字符串或字符數(shù)組的代表,表示其存儲(chǔ)區(qū)域的起始位置,可實(shí)現(xiàn)對(duì)字符串的整體操作。在輸入輸出時(shí),用控制符"%s"來(lái)控制。

例如:定義一個(gè)字符數(shù)組,在其中存放字符串“IloveChina!”,輸出該字符串和第8個(gè)字符。解題思路:用數(shù)組名string和輸出格式%s可以輸出整個(gè)字符串。用數(shù)組名和下標(biāo)可以引用任一數(shù)組元素。#include<stdio.h>voidmain(){charstring[]="IloveChina!";printf("%s\n",string);printf("%c\n",string[7]);//字符數(shù)組法}stringstring+7

例如:通過(guò)字符指針變量輸出一個(gè)字符串。

解題思路:可以不定義字符數(shù)組,只定義一個(gè)字符指針變量,用它指向字符串常量中的字符。通過(guò)字符指針變量輸出該字符串。#include<stdio.h>voidmain(){char*string=”IloveChina!”;printf(”%s\n”,string);//指針?lè)▆char*string;string=”IloveChina!”;#include<stdio.h>voidmain(){char*string=”IloveChina!”;printf(”%s\n”,string);

string=”Iamastudent.”;printf(”%s\n”,string);}#include<stdio.h>intmain(){char*string=”IloveChina!”;printf(”%s\n”,string);

string=”Iamastudent.”;printf(”%s\n”,string);}4.指向字符的指針作函數(shù)參數(shù)9.3.3指針和字符數(shù)組字符指針作為函數(shù)的參數(shù),與指向普通一維數(shù)組的指針基本相同。唯一不同的是:指向普通一維數(shù)組的指針作為參數(shù)時(shí),通常還要加一個(gè)數(shù)組長(zhǎng)度的參數(shù);而字符指針作為函數(shù)參數(shù)時(shí)不用加字符長(zhǎng)度。將一個(gè)字符串從一個(gè)函數(shù)傳遞到另一個(gè)函數(shù),可以用地址傳遞的辦法,可用字符數(shù)組名作參數(shù),也可以用字符指針變量作參數(shù)。在被調(diào)用的函數(shù)中可以改變字符串的內(nèi)容在主調(diào)函數(shù)中可以引用改變后的字符串。字符串指針變量作為函數(shù)實(shí)參時(shí),形參可以是字符指針變量或字符數(shù)組名。當(dāng)字符數(shù)組名作為函數(shù)實(shí)參時(shí),形參可以是字符數(shù)組名,同樣也可以是字符指針變量。9.3.3指針和字符數(shù)組4.指向字符的指針作函數(shù)參數(shù)

【例9.11】把一個(gè)字符串的內(nèi)容復(fù)制到另一個(gè)字符串中,并且不能使用strcpy()函數(shù)。解題思路:定義字符指針*pa、*pb和字符數(shù)組b。在程序中,通過(guò)函數(shù)調(diào)用實(shí)現(xiàn)對(duì)字符串的復(fù)制。函數(shù)定義時(shí),兩個(gè)形參為指針,通過(guò)循環(huán)判斷第一個(gè)形參指針是否指向字符串結(jié)束標(biāo)志實(shí)現(xiàn)字符復(fù)制。函數(shù)調(diào)用時(shí),第一個(gè)實(shí)參為字符指針pa,第二個(gè)實(shí)參為指向字符數(shù)組b的指針pb,形實(shí)結(jié)合后,對(duì)形參p1的操作就是對(duì)實(shí)參pa的操作,對(duì)形參p2的操作就是對(duì)實(shí)參pb的操作,也就是說(shuō)pb和p2指向同一存儲(chǔ)單元。#include<stdio.h>voidmain(){char*pa="welcome",b[100],*pb;

voidcopystring(char*p1,char*p2);pb=b;//字符指針變量pb指向字符數(shù)組bcopystring(pa,pb);//函數(shù)調(diào)用,實(shí)參為字符指針printf("源字符串為:%s\n",pa);printf("賦值字符串為:%s\n",pb);}voidcopystring(char*p1,char*p2){while(*p1!='\0')//字符串長(zhǎng)度由字符串結(jié)束標(biāo)志'\0'決定{

*p2=*p1; p1++; p2++; }

*p2=*p1;//能否省略?}5.字符指針變量和字符數(shù)組的比較存入內(nèi)容不同字符數(shù)組由若干個(gè)元素組成,每個(gè)元素中放一個(gè)字符,而字符指針變量中存放的是地址。(2)賦值方式不同可以對(duì)字符指針變量賦值,但不能對(duì)數(shù)組名賦值。char*a;a=”IloveChina!”;對(duì)charstr[14];str[0]=’I’;對(duì)charstr[14];str=”IloveChina!”;錯(cuò)9.3.3指針和字符數(shù)組(3)存儲(chǔ)單元不同

編譯時(shí)為字符數(shù)組分配若干存儲(chǔ)單元,以存放各元素的值,而對(duì)字符指針變量,只分配一個(gè)存儲(chǔ)單元。char*a;scanf(”%s”,a);錯(cuò)

char*a,str[10];a=str;scanf(”%s”,a);對(duì)9.3.3指針和字符數(shù)組5.字符指針變量和字符數(shù)組的比較(4)修改方式不同指針變量的值是可以改變的,而數(shù)組名代表一個(gè)固定的值(數(shù)組首元素的地址),不能改變。字符數(shù)組中各元素的值是可以改變的,但字符指針變量指向的字符串常量中的內(nèi)容是不可以被取代。

chara[]=”House”,*b=”House”;b[2]=’r’;

9.3.3指針和字符數(shù)組5.字符指針變量和字符數(shù)組的比較9.3.4指向指針的指針如果一個(gè)指針變量存放的是另一個(gè)指針變量的地址,則稱這個(gè)指針變量為指向指針的指針變量,簡(jiǎn)稱為“指向指針的指針”,也稱為“二級(jí)指針”。定義指向指針數(shù)據(jù)的指針變量的一般形式:類型說(shuō)明符**指針變量名;在指針變量名前使用了兩個(gè)“*”號(hào)。右邊的“*”表示該變量是指針類型的變量,左邊的“*”號(hào)表示該變量所指的對(duì)象是指針變量。9.3.4指向指針的指針例如:inti=10;int*p1=&i;//p1指向iint**pp2=&p1;//pp2指向p1&p1pp2&ip110ip1、pp2與i之間的關(guān)系9.3.4指向指針的指針例如

:指向指針數(shù)據(jù)的指針變量。char*name[]={"Follow","Great","FORTRAN","Computer"};

char**p;

inti;for(i=0;i<5;i++){p=name+i;printf("%s\n",*p);}Follow\0Great\0FORTRAN\0Computer\0name[0]name[1]name[2]name[3]namep9.3.4指向指針的指針【例9.12】指向指針的指針。#include<stdio.h>//頭文件voidmain(){inti=10;int*p=&i;//一級(jí)指針變量p聲明并初始化

int**pp=&p;//二級(jí)指針變量pp聲明并初始化

printf("二級(jí)指針變量pp指向地址:%d\n",pp);//輸出

printf("變量p的地址:%d\n",&p);printf("一級(jí)指針變量p指向地址:%d\n",p);printf("變量i的地址:%d\n",&i);printf("i=%d\n",i);printf("p=%d\n",p);printf("*p=%d\n",*p);printf("pp=%d\n",pp);printf("*pp=%d\n",*pp);printf("**pp=%d\n",**pp);}9.3.5指針數(shù)組和數(shù)組指針數(shù)組指針是一個(gè)指針,其指向的數(shù)據(jù)類型由一個(gè)數(shù)組構(gòu)成;而指針數(shù)組的本質(zhì)是一個(gè)數(shù)組,數(shù)組中的每一個(gè)元素用來(lái)保存一個(gè)指針變量。9.3.5指針數(shù)組和數(shù)組指針1.指針數(shù)組的概念指針數(shù)組是指針變量的集合。數(shù)組中的每一個(gè)元素都是指針,且具有相同的存儲(chǔ)類別,并指向相同的數(shù)據(jù)類型。指針數(shù)組通常用來(lái)處理字符串?dāng)?shù)組,提高字符串處理的靈活性。定義一維指針數(shù)組的一般形式為

類型名*數(shù)組名[數(shù)組長(zhǎng)度];char*p[5]={"C","Pascal","Fortran","Java","C#"};9.3.5指針數(shù)組和數(shù)組指針1.指針數(shù)組的概念比較下列兩種字符串的存儲(chǔ)方式chars[5][8]={"C","Pascal","Fortran","Java","C#"};

用二維數(shù)組時(shí),每行的長(zhǎng)度是相同的,需要按最大長(zhǎng)度定義列數(shù),這樣可能會(huì)浪費(fèi)內(nèi)存。char*p[5]={"C","Pascal","Fortran","Java","C#"};用指針數(shù)組時(shí),沒(méi)有定義行的長(zhǎng)度,只是分別在內(nèi)存中存儲(chǔ)不同長(zhǎng)度的字符串,然后用指針數(shù)組的元素分別指向它們,不浪費(fèi)內(nèi)存單元。9.3.5指針數(shù)組和數(shù)組指針1.指針數(shù)組的概念比較下列兩種字符串的存儲(chǔ)方式

用二維數(shù)組s存儲(chǔ)多個(gè)字符串用指針數(shù)組p指向多個(gè)字符串9.3.5指針數(shù)組和數(shù)組指針2.數(shù)組指針二維數(shù)組指針變量是單個(gè)的變量,其定義的一般形式如下:

類型說(shuō)明符(*指針變量名)[數(shù)組長(zhǎng)度]例如:inta[3][4];int(*p)[4];//指向具有4個(gè)元素的數(shù)組p=a[0];9.3.5指針數(shù)組和數(shù)組指針【例9.13】用指針數(shù)組輸出二維數(shù)組中各個(gè)數(shù)組元素的值。#include<stdio.h>voidmain(){inti,j;inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

int*p[3];//p為具有3個(gè)指向整型元素的指針數(shù)組

p[0]=a[0];//第一個(gè)指針數(shù)組元素p[0]指向二維數(shù)組第一行p[1]=a[1];p[2]=a[2];for(i=0;i<3;i++){for(j=0;j<4;j++)

printf("%4d",*(*(p+i)+j)); printf("\n");}}9.3.6主函數(shù)main的形參指針數(shù)組的一個(gè)重要應(yīng)用是作為main函數(shù)的形參。在以往的程序中,main函數(shù)的第一行一般寫(xiě)成以下形式:intmain()或intmain(void)表示main函數(shù)沒(méi)有參數(shù),調(diào)用main函數(shù)時(shí)不必給出實(shí)參。這是一般程序常采用的形式。9.3.6主函數(shù)main的形參實(shí)際上,在某些情況下,main函數(shù)可以有參數(shù),例如:intmain(intargc,char*argv[])

其中,argc和argv就是main函數(shù)的形參,它們是程序的“命令行參數(shù)”。argv是*char指針數(shù)組,數(shù)組中每一個(gè)元素(其值為指針)指向命令行中的一個(gè)字符串。9.3.6主函數(shù)main的形參通常main函數(shù)和其他函數(shù)組成一個(gè)文件模塊,有一個(gè)文件名。對(duì)這個(gè)文件進(jìn)行編譯和連接,得到可執(zhí)行文件(后綴為.exe)。用戶執(zhí)行這個(gè)可執(zhí)行文件,操作系統(tǒng)就調(diào)用main函數(shù),然后由main函數(shù)調(diào)用其他函數(shù),從而完成程序的功能。main函數(shù)是操作系統(tǒng)調(diào)用的,實(shí)參只能由操作系統(tǒng)給出。#include<stdio.h>voidmain(intargc,char*argv[]){inti; for(i=1;i<argc;i++) printf("%s",argv[i]); printf("");}在VC++環(huán)境下編譯、連接后,“工程”—“設(shè)置”—“調(diào)試”—“程序變量”中輸入“ChinaBeijing”,再運(yùn)行就可得到結(jié)果。指針表示二維數(shù)組定義及賦值方式小結(jié)1、int*p,a[3][4];P=&a[0][0];2、int(*p)[4],a[3][4];p=a;3、inta[3][4],*p[3];p[0]=a[0];p[1]=a[1];p[2]=a[2];4、inta[3][4],**p;p=a;9.3.7指向函數(shù)的指針變量用指針變量可以指向一個(gè)函數(shù)。指向函數(shù)的指針變量簡(jiǎn)稱函數(shù)指針。函數(shù)在編譯時(shí)被分配給一個(gè)入口地址。這個(gè)函數(shù)的入口地址就稱為函數(shù)的指針。函數(shù)指針有兩個(gè)用途:調(diào)用函數(shù)和作為函數(shù)的參數(shù)。9.3.7指向函數(shù)的指針變量可以定義一個(gè)指向函數(shù)的指針變量,用來(lái)存放某一函數(shù)的起始地址,這就意味著此指針變量指向該函數(shù)。定義指向函數(shù)的指針變量的一般形式為

數(shù)據(jù)類型(*指針變量名)(函數(shù)參數(shù)表列);例如:int(*p)(int,int);

定義p是指向函數(shù)的指針變量,它可以指向類型為整型且有兩個(gè)整型參數(shù)的函數(shù)。p的類型用int(*)(int,int)表示9.3.7指向函數(shù)的指針變量如

:int(*p)(int,int);p=max;對(duì)

p=max(a,b);錯(cuò)

指向函數(shù)的指針變量不能進(jìn)行算術(shù)運(yùn)算,p+n,p++,p--等運(yùn)算無(wú)意義

將函數(shù)max的入口地址賦給指針變量p將調(diào)用max的函數(shù)值賦給指針變量p9.3.7指向函數(shù)的指針變量【例9.15】用指向函數(shù)的指針變量,求三個(gè)整數(shù)的最大值。(1)算法分析定義一個(gè)函數(shù)指針變量int(*p)(int,int),可以將具有相同返回值類型及相同形參類型及個(gè)數(shù)的不同函數(shù),調(diào)用后,由函數(shù)指針變量將函數(shù)值的入口地址帶回。如求兩個(gè)整數(shù)的最大值和最小值的不同函數(shù)均可由函數(shù)指針調(diào)用后返回,更具有通用性。(2)程序設(shè)計(jì)#include<stdio.h>intmax(intx,inty);//函數(shù)聲明voidmain(){inta,b,c,m;

int(*p)(int,int); p=max;//將函數(shù)max的入口地址賦值給指針變量p

scanf("%d%d%d",&a,&b,&c);

m=(*p)(a,b);//調(diào)用max函數(shù),等價(jià)于max(a,b) m=(

溫馨提示

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