計算機第8章 指針_第1頁
計算機第8章 指針_第2頁
計算機第8章 指針_第3頁
計算機第8章 指針_第4頁
計算機第8章 指針_第5頁
已閱讀5頁,還剩121頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第8章指針

第8章指針

8.1指針的概念

8.2指針變量的定義與引用

8.3指針運算

8.4指針和數(shù)組

8.5指針與字符串

8.6指針數(shù)組和指向指針的指針

8.7指針與內(nèi)存的動態(tài)分配

8.8指針與數(shù)卵.作為函數(shù)的參數(shù)

8?9帶參數(shù)的main函數(shù)

8.10返回指針侑的函數(shù)

8.11函數(shù)指針的定義與引用

8.12本章小結(jié)

,Bdck4

第8章指針---------------------------------

8.1指針的概念

8.1.1變量的地址與變量的內(nèi)容

計算機為了方便管理內(nèi)存,為每一個內(nèi)存單元都

編了號,這個編號稱為內(nèi)存單元的地址。一般把存儲

器中的一個字節(jié)稱為一個內(nèi)存單元(亦稱存儲單元),變

量的地址與變量的內(nèi)容是兩個不同的概念。變量在內(nèi)

存中所占存儲空間的首地址就稱為變量的地址。而變

量在內(nèi)存所占的內(nèi)存單元中存放的數(shù)據(jù)就稱為變量的

內(nèi)容。

,Bdck4

盛露第8章指針_________________________________

8.1.2直接訪問與間接訪問

變量值的存取都是通過地址進行的,例如:

priintf(''%d〃,&i)的執(zhí)行是這樣的。先找到變量i的地址

200,然后從200開始的兩個字節(jié)中取出數(shù)據(jù)(假若變

量i的值為5)把它輸出。這種按變量地址存取變量的

方式稱為直接訪問方式。還可以采用另一種稱為間接

訪問方式,將變量i的地址存放在另一個變量中。假設(shè)

一個變量P,用來存放變量i的地址,它被分配為300,

301兩個單元。將i的地址存放到p中,要存取變量i的

值,先找到存放i地址的變量P,從P中取出i的地址

(200),然后到200,201中取出i的值5。

<Bdck<

莖0第8章指針

8.1.3指針與指針變量

對于一個內(nèi)存單元來說,單元的地址即為指針,

其中存放的數(shù)據(jù)是該單元的內(nèi)容。在C語言中,允許用

一個變量來存放指針,這種變量稱為指針變量。因此,

一個指針變量的值就是某個內(nèi)存單元的地址,或稱為

某內(nèi)存單元的指針。

,Bdck4

莖0第8章指針

PC

II

0110H?----------力

0110H(地址)

圖8.1指向變量C的指針變量P

,Bdck4

熱第8章指針_________________________________

如圖8-1所示,設(shè)有字符變量C,其內(nèi)容為K

(ASCII碼為十進制數(shù)75),C占用了0110H號單元(地址

用十六進制表示)。當有指針變量P,內(nèi)容為0110H時,

我們稱為“P指向變量C〃或者“P是指向變量C的指

針”。

嚴格地說,一個指針是一個地址,是一個常量,

而一個指針變量卻可以被賦予不同的指針值,是變量。

但通常把指針變量簡稱為“指針”。為了避免混淆,

我們約定:“指針”是指地址,是常量,“指針變量”

是指取值為地址的變量。定義指針的目的是為了通過

指針去訪問內(nèi)存單元。

<Bdck<

盛露第8章指針_________________________________

既然指針變量的值是一個地址,那么這個地址不

僅可以是變量的地址,而且也可以是其他數(shù)據(jù)結(jié)構(gòu)的

地址。在一個指針變量中存放一個數(shù)組或一個函數(shù)的

首地址有何意義呢?因為數(shù)組或函數(shù)都是連續(xù)存放的,

所以通過訪問指針變量取得了數(shù)組或函數(shù)的首地址,

也就找到了該數(shù)組或函數(shù)。這樣一來,凡是出現(xiàn)數(shù)組、

函數(shù)的地方都可以用一個指針變量來表示,只要該指

針變量中賦予數(shù)組或函數(shù)的首地址即可。這樣做,將

會使程序的概念十分清楚,程序本身也精練、高效。

,Bdck4

盛露第8章指針_________________________________

在C語言中,一種數(shù)據(jù)類型或數(shù)據(jù)結(jié)構(gòu)往往都占

有一組連續(xù)的內(nèi)存單元。用“地址”這個概念并不能

很好地描述一種數(shù)據(jù)類型或數(shù)據(jù)結(jié)構(gòu),而“指針”雖

然實際上也是一個地址,但它卻是一個數(shù)據(jù)結(jié)構(gòu)的首

地址,它是“指向”一個數(shù)據(jù)結(jié)構(gòu)的,因而概念更為

清楚,表示更為明確。這也是引入“指針”概念的一

個重要原因。

,Bdck4

函露第8章指針

8.2指針變量的定義與引用

821指針變量的定義

指針變量定義的一般形式為

類型說明符*指針變量名;

其中,*為說明符,表示這是一個指針變量;指針

變量名為用戶自定義標識符;類型說明符表示該指針

變量所指向的變量的數(shù)據(jù)類型。

,Bdck4

遍露第8章指針

例如:

int*pl;

該定義表示pl是一個指針變量,它的值是某個整

型變量的地址,或者說pl指向一個整型變量。至于pl

究竟指向哪一個整型變量,應由向pl賦予的地址來決

定。對于指針變量的類型說明應包括以下三個方面的

內(nèi)容:

(1)指針類型說明,即定義變量為一個指針變量。

(2)指針變量名。

(3)變量值,即指針變量所指向變量的地址。

,Bdck4

莖0第8章指針

例如:

staicint*p2;

/*p2是指向靜態(tài)整型變量的指針變量*/

float*p3;/*p3是指向浮點型變量的指針變量*/

char*p4;/*p4是指向字符型變量的指針變量*/

應該注意的是,一個指針變量只能指向同類型的

變量,如P3只能指向浮點型變量,不能時而指向一個

浮點型變量,時而又指向一個字符型變量。

,Bdck4

盛露第8章指針_________________________________

8.2.2指針變量的引用

指針變量同普通變量一樣,使用之前不僅要定義

說明,而且必須賦予具體的值。未經(jīng)賦值的指針變量

不能使用,否則將造成系統(tǒng)混亂,甚至死機。同時,

指針變量的賦值只能賦予地址,決不能賦予任何其他

數(shù)據(jù),否則將引起錯誤。

在C語言中,初始變量的地址是由編譯系統(tǒng)分配

的,對用戶完全透明,用戶不知道變量的具體地址。

,Bdck4

盛露第8章指針_________________________________

C語言中提供了地址運算符&來表示變量的地址。

其一般形式為

&變量名

如&a表示變量a的地址,&b表示變量b的地址。變

量本身必須預先說明或定義。

設(shè)有指向整型變量的指針變量P,如要把變量a的

地址賦予p可以有以下兩種方式:

(1)指針變量初始化的方法:

inta;

int*p=&a;

,Bdck4

盛露第8章指針_________________________________

(2)賦值語句的方法:

inta;

int*p;

p=&a;

不允許把一個數(shù)賦予指針變量,如下面的賦值是

錯誤的:

int*p;

p=1000;

被賦值的指針變量前不能再加"”說明符,如寫

為*p=&a也是錯誤的。

,Bdck4

盛露第8章指針_________________________________

8.3指針運算

8.3.1指針變量的算術(shù)運算

指針變量可以進行某些運算,但其運算的種類是

有限的:如部分算術(shù)及關(guān)系運算。

設(shè)px與py是指向具有相同類型且連續(xù)存儲的一組數(shù)

據(jù)。如指向同一個數(shù)組。若n代表整數(shù),則指針可進行

下列加減運算。

px±n,px++,px--,++px,--px,px-py;py-px;

(1)px+n.就是“px的地址土n*px的類型占用的單

元數(shù)”所對應的地址。

,Bdck4

函露第8章指針

(2)px++,++px,px—,一px.顯然是px±n的特

(n=l)o即指針加1或減1。

(3)px-py,py-px兩個指針相減運算結(jié)果

是整數(shù),即它們所指向數(shù)組元素下標相差的整數(shù)。

設(shè)px指向數(shù)組元素a[2],py指向數(shù)組元素a[6],則

下列表達式及其運算結(jié)果:

px-py結(jié)果為整數(shù)-4。

py-px結(jié)果為整數(shù)4o

<Bdck<

挑第8章指針_________________________________

【例8.1】指針變量的定義、賦值及簡單應用

main()

{inta=5,*p=&a;

printf(”%d”,*p);

)

程序運行情況:

5

程序說明:在定義指針變量p后,利用指針變量p

取得整型變量a的地址,并在最后的輸出中,利用指針

變量獲取變量a的值進行輸出。

<Bdck<

盛露第8章指針_________________________________

8.3.2指針的關(guān)系運算

它的運算規(guī)則是:當兩個指針變量的值(地址值)

潢足關(guān)系運算時,結(jié)果為1(真);否則結(jié)果為0

(假),所以兩個指針變量進行關(guān)系運算的結(jié)果也是

邏輯值。

定義了數(shù)組a和同類型的指針變量px,py;使px指向數(shù)

組元素a[l];py指向數(shù)組元素a[4]。請看下列的關(guān)系

表達式及其運算結(jié)果:

px<py結(jié)果為1(真)。

px++==py結(jié)果為0(假),注意++是后綴。

,Bdck4

莖0第8章指針

_py==pX+2結(jié)果為1(真),注意-是前綴。

py<&a[5]結(jié)果為1(真),&a[5]地址是地址常量。

py>=px+2結(jié)果為1(假),px+2是地址型表達式,

代表a[3]的地址。

指什的運算應注意以下幾點:

?指什變量只能和整數(shù)或整型變量相加減,而不能和

實型數(shù)或?qū)嵭妥兞肯嗉訙p。如px+3.5是錯誤的

?指什變量不能進行乘法和除法運算。如py*4或py/2

都是錯誤的。

兩個指什變量相減,必須指向同一個數(shù)組,否則不能進

行減法運算。

,Bdck4

函露第8章指針

8.4指針和數(shù)組

8.4.1指針與一維數(shù)組

定義一個整型數(shù)組和一個指向整型的指針變量如下

inta[10],*p;

假定給出賦值運算

p=&a[O];

此時,p指向數(shù)組中的第0號元素,即a[0],指針變量p中包

含了數(shù)組元素a[0]的地址,由于數(shù)組元素在內(nèi)存中是連

續(xù)存放的,因此,我們就可以通過指針變量p及其有關(guān)運

算間接訪問數(shù)組中的任何一個元素。

,Bdck4

函露第8章指針

則表示元素地址還可以用a+i,p+i,&p[i],

表示數(shù)組中元素a[i],還可以用p[i],*(a+i),*(p+i)。

下面我們用指針給出數(shù)組元素的地址和內(nèi)容的幾種表示形式。

(1)p+i和a+i均表示的地址,它們均指向數(shù)組第i號元

素,即指向a[i]0

(2)*(p+i)和*(a+i)都表示p+i和a+i所指對象的內(nèi)容,

即為a[i]o

(3)指向數(shù)組元素的指針,也可以表示成數(shù)組的形式,也

就是說,它允許指針變量帶下標,如p[i]與*(p+i)等價。

<Bdck<

盛露第8章指針_________________________________

【例8.2]數(shù)組與指針變量的綜合應用舉例。

方法1:用下標法引用數(shù)組元素。

main()

{inta[10],i;

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

nn

scanf(%d?&a[i]);

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

printf(n%d\a[i]);

,Bdck4

/露第8章指針_________________________

方法2:用指針變量法引用數(shù)組元素。

main()

{inta[10]/p,i;

p=a;

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

scanf(”%d”,p+i);

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

printf(n%dn,*(p+i));

,Bdck4

盛露第8章指針_________________________________

方法3:通過指針變量自增運算引用數(shù)組元素。

main()

{inta[10]/p;

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

scanf(n%dn,p);

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

printf(”%d”,*p);

,Bdck4

揶第8章指針______________________________

方法4:用指針的下標表示法引用數(shù)組元素。

mainQ

{inta[10],*p,i;

p=a;

for(i=O;i<10;i++)

scanf(n%dn,&p[i]);

fbr(i=O;i<10;i++)

printf(n%dn,p[i]);

}

程序運行結(jié)果為:

1234567890/

1234567890

<Bdck<

盛露第8章指針_________________________________

8.4.2指針與二維數(shù)組

用指針可以指向一維數(shù)組,也可以指向二維數(shù)組。

1.二維數(shù)組的地址

為了說明問題,我們定義以下二維數(shù)組:

inta[2][4]={{0,l,2,3},{4,5,6,7}};

a為二維數(shù)組名,此數(shù)組有3行4列,共12個元素。但也可這

樣來理解,數(shù)組a由二個元素組成:a[0]9a[l]o而它們中

每個元素又是一個一維數(shù)組,且都含有4個元素,例如,

a[0]所代表的一維數(shù)組所包含的4個元素為

a[0][l],a[0][2],a[0][3]o

,Bdck4

莖0第8章指針

如圖8.2所示:

a[0]0.123

a[l]4567

圖8.2a[O],a[l]代表二維數(shù)組中的行

但從二維數(shù)組的角度來看,a代表二維數(shù)

組的首地址,當然也可看成是二維數(shù)組第0

行的首地址。a+1就代表第1行的首地址。

如果此二維數(shù)組的首地址為1000,由于第0

行有4個整型元素,所以a+1為1008。如圖

8.3所示

<Bdck<

第8章指針_________________________

a[0]a[O]+la[0]+2

a[0]+3

a?1000100210041006

0123

a+4-----a1008101010121014

4567

圖8.3二維數(shù)組中的行地址和列地址示意圖

二維數(shù)組元素明口]可表示成*(咽+j)或

*(*(a+i)+j),它們都與a[i]用等價,或者還可寫成

(*(a+i))[j]o見表8.1

,Bdck4

莖0第8章指針

表8.1指針變量的含義及對應地址

含義地址

a一維數(shù)組首地,0行首地1000

a[O]+O,*(a+O),*a表第0行第0列兀素地址1000

a+l,a[l]第1行首地址1008

a[l]+2,*(a+l)+2,&a[l][2]第1行第2列兀素地址1012

*(a[l]+2),*(*(a+l)+2),第1行第2列兀素的值6

a[l][2]

*(a[i]+j),*(*(a+i)+j),a[i]U]第i行第j列元素的值

,Bdck4

盛露第8章指針_________________________________

另外,要補充說明一下,如果你編寫一個程序輸出打

印2和*%你可發(fā)現(xiàn)它們的值是相同的,這是為什么呢?

我們可這樣來理解:首先,為了說明問題,我們把二維數(shù)

組人為地看成由兩個數(shù)組元素a[0],a[l]組成,將a[0],

a[l]]看成是數(shù)組名它們又分別是由4個元素組成的一維

數(shù)組。因此,a表示數(shù)組第0行的地址,而*a即為a[0],它

是數(shù)組名,當然還是地址,它就是數(shù)組第0行第0列元素

的地址。

,Bdck4

盛露第8章指針___________________________________

2指向二維數(shù)組的指針變量

在了解上面的概念后,可以用指針變量指向二維數(shù)組及其元素。

(1)指向數(shù)組元素的指針變量

【例8.3]用指針變量輸出數(shù)組元素的值。

mainQ

{staticinta[2][4]={1,2,3,4,5,6,7,8};int*p;

fbr(p=a[O];p<a[0]+8;p++)

{if((p-a[0])%4=0)printf(n\nn);printf(n%4dn,*p);}

}

程序運行結(jié)果為:

1234

5678

<Bdck<

盛露第8章指針___________________________________

如果讀者對p的值還缺乏具體概念的話,可以把p的值(即數(shù)組

元素的地址)輸出。若將程序最后兩行改為:

printf("元素地址=%o,元素值=%4d\n”,p,*p);

這時輸出如下:

元素地址=236,元素值=1

元素地址=240,元素值=2

元素地址=242,元素值=3

元素地址=244,元素值=4

元素地址=246,元素值=5

元素地址=250,元素值=6

元素地址=252,元素值=7

元素地址=254,元素值=8

<Bdck<

盛露第8章指針_________________________________

計算用]口]在數(shù)組中的相對位置的計算公式為:

i*mtj

其中m為二維數(shù)組的列數(shù)(二維數(shù)組大小為n*m).例如,

對3*4(3行4列)的二維數(shù)組,它的第2行第3列元素

(a⑵[3])對a[0][0]的相對位置為2*4+3=11。

可以看到,C語言規(guī)定數(shù)組下標從0開始,對計算上述

相對位置比較方便,只要知道i和j的值,就可以直接用

i*m+j公式計算出相對于數(shù)組開頭的相對位置。如

果規(guī)定下標從1開始,則計算[j]的相對位置所用的公

式就要改為:(i-l)*m+(j-1),這就增加了計算的工作量。

,Bdck4

莖0第8章指針

(2)指向由.m個整數(shù)組成的一維數(shù)組的指針變量

這里的指針變量P不是指向整型變量,而是指向一個

包含m個元素的一維數(shù)組。如果p先指向a[0],貝1Jp+1

不是指向而是指向a[l],p的增值以一維數(shù)

組的長度為單位,見圖8.4

P.a

----------------

S[口]

.------------

p+2敲1]

-----A---------

或一

國QZL指向皿個元素的一k

紹&4維數(shù)組的指針變量

<Bdck<

函露第8章指針

【例8.4】輸出二維數(shù)組任一行任一列元素的值。

main()

{inta[3][4]={l,3,5,7,9,HJ3,15,17,19,21,23};

int(*p)[4],ij;

p=a;

scanf("i=%d,j=%d”,&i,&j);

,n

printfCa[%d][%d]=%d\n?i?j,p[i]|j]);

<Bdck<

盛露第8章指針_________________________________

程序運行結(jié)果為:

i=l,j=2/(本行為鍵盤輸入)

a[l][2]=13

程序第三行“int(*p)[4『表示P是一個指針變量,它指向包

含4個元素的一維數(shù)組。注意*P兩側(cè)的括號不可缺少,如

果寫成*P[4],由于方括號口運算級別高,因此P先與[4]結(jié)

合,是數(shù)組,然后再與前面的*結(jié)合,*p[4]是指針數(shù)組

(參看本章8.6).有的讀者感到"(*p)[4]〃這種形式不好

理解。

程序的p+i是二維數(shù)組a的第i行的地址,*(p+2)+3是a

數(shù)組第2行第3列元素地址,這是指向列的指針,

*((*p+2)+3)是a[2][3]的值。

,Bdck4

盛露第8章指針_________________________________

8.5指針與字符串

8.5.1字符串的表示與引用

在C語言中,既可以用字符數(shù)組表示字符串,也可用

字符指針變量來表示;引用時,既可以逐個字符引用,

也可以整體引用。

前面章節(jié)中介紹了用字符數(shù)組來表示字符串,以及

對字符的引用。本節(jié)重點介紹利用字符指針變量對字符

串的表示和引用。

,Bdck4

盛露第8章指針_________________________________

1逐個引用

【例8.5】使用字符指針變量表示和引用字符串。

main()

{char*string="Beijing2008.n;

while(*string!-\0!)

{print4"%c",*string);string++;}

printf(n\n\nn);

)

程序運行結(jié)果為:

Beijing2008.

,Bdck4

函露第8章指針

注意:

(1)字符指針變量string中,僅存儲串常量的首地

址、而串常量的內(nèi)容(即字符串本身)存儲由系統(tǒng)自動

開辟的內(nèi)存中,并在串尾添加一個結(jié)束標志'\0'。

(2)若定義了一個指針變量,使它指向一個字符串

后,可以用下標形式引用指針變量所指的字符串中的字

符。如:

,Bdck4

盛露第8章指針_________________________________

【例8.6]

#include"stdio.h"

main()

{char*a="Beijing2008.”;

inti=0;

printff'Thelengthofthestringis%d\nn,strlen(a));

while(a[i]!='\0')

{putchar(a[i]);i++;}

putchar(,\n,);

,Bdck4

第8章指針---------------------------------

程序運行結(jié)果為:

Thelengthofthestringis13

Beijing2008.

2整體引用

【例8.71對【例8.6】采取整體引用的辦法。

main()

{char*string="Beijing2008.n;

nn

print%s\n9string);

,Bdck4

盛露第8章指針_________________________________

程序運行結(jié)果為:

Beijing2008.

說明:printf("%s\n\string);語句通過指向字符串的

指針變量string,整體引用它所指向的字符串。其原

理是:系統(tǒng)首先輸出string指向的第一個字符,然后

使string自動加1,使之指向下一個字符;重復上述過

程,直至遇到字符串結(jié)束標志。

顯然,對于字符串輸出而言,整體引用比逐個字

符引用更簡潔。

,Bdck4

盛露第8章指針_________________________________

3字符指針變量與字符數(shù)組的比較

雖然用字符指針變量和字符數(shù)組都能實現(xiàn)字符串的存儲

和處理,但二者是有區(qū)別的,不能混為一淡。

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

字符指針變量中存儲的是字符串的首地址,而字符數(shù)組

中存儲的是字符串本身(數(shù)組的每個元素存放一個字

符)。

(2)賦值方式不同

對于字符指針變量,可采用下面的賦值語句賦值:

char*p;

p="Howareyou!,r;

,Bdck4

盛露第8章指針----------------------------

(3)指針變量的值是可以改變的,字符指針變量也不例

外,而數(shù)組名代表數(shù)組的起始地址是一個常量,而常量

是不能被改變的。

例如:char*p="Howareyou!";

p=p+3;

printf(n%s",a);

針變量a的值可以變化,輸出字符串從當前所指向的

單元開始輸出各個字符,直到'\0,為止,而數(shù)組名代表

地址,但它的值是不能改變的。以下為錯誤賦值。

charstr[]二〃Howareyou!〃;

str=str+3;/*不能給常量賦值*/

,Bdck4

函露第8章指針

8.6指針數(shù)組和指向指針的指針

8.6.1指針數(shù)組

其元素均為指針類型數(shù)據(jù)的數(shù)組,稱為指針數(shù)組。指針

數(shù)組中的每一個元素都相當于一個指針變量,且這些指

針變量指向相同數(shù)據(jù)類型的變量。

指針數(shù)組定義的一般形式為:

類型名*數(shù)組名[整型常量];

其中,“整型常量”規(guī)定了指針數(shù)組的長度,類型名則

代表指針數(shù)組元素可以指向的數(shù)據(jù)類型。

,Bdck4

莖0第8章指針

例如,

int*p[6];

由于[]比*優(yōu)先級高,因此p先與[6]結(jié)合,形成p[6]形

式,這顯然是數(shù)組形式,它有6個元素,然后再與前面的

結(jié)合表示此數(shù)組是指針類型的,每個數(shù)組元

素(相當于一個指針變量)都可以指向一個整型變量。

即p有6個元素的數(shù)組,每個元素是一個指向int類型數(shù)據(jù)

的指針。

注意:int*p注]與int(*p)[6],請讀者自行分析。

<Bdck<

盛露第8章指針_________________________________

【例8.8]編程將如下表示地址名的字符串按字母順序由小

到大排序,然后輸出這些字符串:Beijing,Shanghai,

Nanchang,Guangzhouo

#include"stdio.h"

main()

{intij;chartemp[10];

charstr[4][10]=

{"Beijing"JShanghai"JNanchang"JGuangzhou''};

printff'Beforesorted:\nn);

for(i=0;i<4;i++)printf,%s,9\str[i]);/*輸出排序前

的5個字符串*/

,Bdck4

盛露第8章指針_________________________________

/*交換法排序*/

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

for(j=i+l;j<4;j++)

if(strcmp(str[j],str[i])<0)

{/*則交換str[j]所指字符串和str[i]所字符串*/

strcpy(temp,str[i]);

strcpy(str[i],str[j]);

strcpy(str[j],temp);

<Bdck<

函露第8章指針

printff'\nAftersorted:\nn);

for(i=0;i<4;i++)printf(n%s,n,str[i]);/*輸出排序

后的4個字符串*/

)

程序運行結(jié)果為:

Beforesorted:

Beijing,Shanghai,Nanchang,Guangzhou,

Aftersorted:

Beijing,Guangzhou,Nanchang,Shanghai,

,Bdck4

熱第8章指針_________________________________

對于二維數(shù)組與指針數(shù)組之間的區(qū)別初學都有常常會感到

困惑,例如:

charstr[4][10]={"Beijing","Shanghai",

"Nanchang","Guangzhou”};

char*ptr[4]={"Beijing","Shanghai",

"Nanchang"/Guangzhou”};

雖然str[i]和ptr[i]都代表第i+1個字符串的首地址,都是對第

i+1字符串的合法引用,但str與ptr的含義卻又完全不同:

,Bdck4

函露第8章指針

str代表一個真正的二維數(shù)組,str是它的

名字,編譯時需分配4*10個字節(jié)的存儲空間

用于存放40個字符型數(shù)據(jù),同時將初紹化列

表中提供的字符串賦值給字符數(shù)組的元素,

而對于指針數(shù)組ptr只需分配4個用于存放指

針型數(shù)據(jù)的存儲單元即可。

,Bdck4

函露第8章指針

8.6.2指向指針的指針

指向指針數(shù)據(jù)的指針變量,簡稱為指向指針的指針。

定義一個指向指針數(shù)據(jù)的指針變量,格式如下:

類型符**指針變量;

如:char**p;

p的前面有兩個*號。*運算符的結(jié)合性是從右到左,因此

**p相當于*(*p),顯然*p是指針變量的定義形式。

,Bdck4

函露第8章指針

861節(jié)中介紹了指針數(shù)組,該類數(shù)組中的元

素是指針型數(shù)據(jù),故指針數(shù)組中的元素也可看作

是指向指針的指針,即所謂的二級指針變量。

下面舉例說明指針數(shù)組和指向指針的指針的

使用方法。

,Bdck4

函露第8章指針

【例8.9】指針數(shù)組與指向指針的指針使用舉例。

main()

{char*name[]={"Followme"JBASIC","GreatWall",

"FORTRAN”「'computerdesign"};

char**p;

inti;

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

{p=name+i;printf,%s\n”,*p);}

,Bdck4

盛露第8章指針_________________________________

運行結(jié)果如下:

Followme

BASIC

FORTRAN

GreatWall

Computerdesign

程序說明:p是指向指針的指針變量,在第一次執(zhí)行循環(huán)

體時,賦值語句“p=name+i;”使p指向name數(shù)組的0號元

素name[0],*p是name[0]的值,即第一個字符串的起始地址,

用printf函數(shù)輸出第一個字符串(格式符為%s),依次輸出

5個字符串。

<Bdck<

盛露第8章指針_________________________________

指針數(shù)組的元素也可以不指向字符串,而指向整型數(shù)

據(jù)或?qū)嵭蛿?shù)據(jù)等,例如:

inta[5]={l,3,5,7,9};

int*num[5]

int**p;

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

num[i]=&a[i];

例8.10是一個指針數(shù)組的元素指向整型的簡單例子。

,Bdck4

盛露第8章指針____________________________

【例8.10】

main()

{staticinta[5]={l,355,7,9};

staticint*num[5]={&a[0],&a[l],&a[2],&a[3],&a[4]};

int**p,i;p=num;

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

{printf("%d\t",**p);p++;}

}

運行結(jié)果為:

13579

,Bdck4

函露第8章指針

8.7指針與內(nèi)存的動態(tài)分配

c語言有兩種分配內(nèi)存的方式:

靜態(tài)內(nèi)存分配方式和動態(tài)內(nèi)存分配方式。

靜態(tài)內(nèi)存分配方式:

是指所占用的數(shù)據(jù)存儲位置和字節(jié)數(shù)在程序運行過程

中是固定不變的。

缺點是:對于事先無法準確估計數(shù)據(jù)量的情況下,無

法做到既滿足處理需要,又不浪費內(nèi)存空間。

,Bdck4

函露第8章指針

動態(tài)內(nèi)存分配方式:

是指在程序運行過程中,根據(jù)程序的實際需要分配

一塊大小合適的內(nèi)存。程序可以動態(tài)地分配給一個數(shù)

組,也可以動態(tài)地分配給其它類型的數(shù)據(jù)單元。動態(tài)

分配的內(nèi)存只需要一個指針變量,記錄內(nèi)存的地址。

優(yōu)點是:動態(tài)內(nèi)存區(qū)能用于不同的任務。對于一個

任務分配占用了的內(nèi)存,當該任務完成以后就可釋放

并收回,以后又可再把它們重新分配給其它的任務使

用。

,Bdck4

第8章指針

下面就介紹C語言編譯系統(tǒng)庫函數(shù)提供的有關(guān)動態(tài)內(nèi)存

分配的幾個函數(shù)。

1malloc()函數(shù)

調(diào)用方式:

void*malloc(unsigenedsize)

功能:在內(nèi)存的動態(tài)存儲區(qū)中分配一個長度為size個字

節(jié)的連續(xù)空間。此函數(shù)的返回值是一個指向分配域起始地

址的指針(基類型為void),若此函數(shù)未能調(diào)用成功(例

如,內(nèi)存空間不足),則返回空指針(NULL)。

,Bdck4

盛露第8章指針_________________________________

如果要將函數(shù)調(diào)用的返回值賦給某個指針,則應根

據(jù)該指針的類型將返回值進行強制類型轉(zhuǎn)換。

例如:

int*pl;

pl=(int*)malloc(10);

其中,malloc(10)表示申請了一個長度為10個字節(jié)的存儲

空間。malloc(10)的返回值經(jīng)強制類型轉(zhuǎn)換后賦給指針

變量pl,即執(zhí)行語句pl=(int*)malloc(10)后,表示用一個

指向int數(shù)據(jù)的指針變量pl指向了這段存儲空間的首地址。

,Bdck4

盛露第8章指針_________________________________

2colloc()函數(shù)

調(diào)用方式:

void*colloc(unsigenedn,unsigenedsize)

功能:在內(nèi)存的動態(tài)存儲區(qū)中分配n個長度為size個字

節(jié)的連續(xù)空間。此函數(shù)的返回值是一個指向分配域起始

地址的指針(基類型為void),如果分配不成功,則返回

空指針(NULL),若要將返回值賦給某個指針,要進行

強制類型轉(zhuǎn)換。例如:

float*p2;

p2=(float*)calloc(10,sizeof(float));

<Bdck<

藍露第8章指針_________________________________

表示系統(tǒng)申請了10個連續(xù)的float類型的存儲單元,并用

指針p2指向連續(xù)存儲單元的首地址。

3firee()函數(shù)

調(diào)用方式:

voidfree(void*p)

功能:釋放由p指向的內(nèi)存區(qū),使這部分內(nèi)存區(qū)能被其

它變量使用,該函數(shù)無返回值。

例如,為將前面已申請的指向整型數(shù)據(jù)的指針pl,所指

向的確10個字節(jié)的存儲空間釋放掉,可使用下列語句:

free(pl);

,Bdck4

盛露第8章指針_________________________________

【例8.12】編程輸入一個班的某課程的學生成績,計算其

平均分,然后輸出。班組人數(shù)由用戶用鍵盤輸入。

程序如下:

#include<stdio.h>

#include<stdlib.h>

main()

{int*p,n,i,sum;

printff'Pleaseenterarraysize:");

scanf(n%dn,&n);/*輸入學生人數(shù)*/

,Bdck4

函露第8章指針

p=(int*)malloc(n*sizeof(int));/*向系統(tǒng)申請n個sizeof(int)字節(jié)的連續(xù)

存儲空間*/

printf(nPleaseenterthescore:11);

for(i=0;i<n;i++)/*輸入每個學生的分數(shù)*/

scanf(n%dn,p+i);/*累加變量sum賦初值*/

sum=0;

fdr(i=0;i<n;i++)

sum=sum+*(p+i);/*計算總分數(shù)*/

printff''aver=%d\n:,sum/n);/*打印平均分*/

free(p);/*釋放向系統(tǒng)申請的存儲空間*/

<Bdck<

盛露第8章指針_________________________________

程序運行結(jié)果如下:

Pleaseenterarraysize:5/

Pleaseenterthescore:9085709580

aver=84

說明:

⑴malloc()和calloc()函數(shù)是動態(tài)內(nèi)存分配函數(shù),

如果分配失敗則返回空指針,所以可以檢查是否分配

成功。若分配失敗可用exit(l)函數(shù)終止程序運行。

,Bdck4

函露第8章指針

(2)free。函數(shù)只能用于已由malloc()和colloc()

分配地址的指針來調(diào)用。如用其它指針來調(diào)用則可

能破壞內(nèi)存管理機制,造成對系統(tǒng)的破壞。

⑶malloc()>caolloc()>free()函數(shù)原形

對于ANSI標準在“stdlib.h”頭文件中,而其它C編

譯則在“alloc.h”頭文件中。

,Bdck4

函露第8章指針

8.8指針與數(shù)組作為函數(shù)的參數(shù)

8.8.1指針變量作為函數(shù)的參數(shù)

指針變量,既可以作為函數(shù)的形參,也可以作為

函數(shù)的實參,指針變量作實參時,與普通變量一樣,也

是〃值傳遞〃。即將指針變量的值傳遞給調(diào)函數(shù)的形

參。但由于指針變量的值是一個地址,實際是實現(xiàn)

“地址的傳遞”。

,Bdck4

遍露第8章指針

【例8.13】

mainQ

{voidsub(int*px,int*py)

intx=8,產(chǎn)11;

nn

printf(%d,%d\n,x?y);

sub(&x,&y);

nn

printf(%d,%d\n,x?y);

<Bdck<

函露第8章指針

voidsub(int*px,int*py)

{*px=10;

*py=20;

}

運行結(jié)果:

8,11

10,20

<Bdck<

盛露第8章指針_________________________________

說明:

對sub()函數(shù)調(diào)用時,實參是x變量的地址和y變量

的地址,它們分別傳遞給指針變量px和py,即參數(shù)傳

遞后px指向x變量.py指向y變量,執(zhí)行*px=10;

*py=20;語句后把px地址的內(nèi)容賦值為10,py地址內(nèi)

容賦值為20。函數(shù)調(diào)用結(jié)束后,這兩個地址的值已經(jīng)

改變.即x=10;y=20;此例采用傳址方式,通過被調(diào)

函數(shù)參數(shù)的改變,影響主調(diào)參數(shù)。

,Bdck4

/露第8章指針_____________________________

【例8.14】求一維數(shù)組中全部元素之和

intadd(int*pt,intn)

{inti,sum=O;

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

sum=sum+pt[i];

return(sum);

,Bdck4

/露第8章指針________________

main()

{inta[10]={l,2,3A5965758,9,10};

int*p,total;

p=a;

total=add(p,10);

printf(ntotal=%d\nn,total);

)

運行結(jié)果:

total=55

<Bdck<

莖0第8章指針

8.8.2數(shù)組名作為函數(shù)的參數(shù)

指針的本質(zhì)是地址,而數(shù)組名代表數(shù)組的首地

址。指針可以作為參數(shù),數(shù)組名也就可以做參數(shù),

一維數(shù)組名作為函數(shù)形參時,數(shù)組名后面要跟著

口,口中間可以有整數(shù)常量,也可以沒有,其

實一維數(shù)組參數(shù)的函數(shù)名后面的口只是一個標記,

中間的整數(shù)將被忽略。

,Bdck4

盛露第8章指針-----------------------

【例8.15】求一維數(shù)組各元素的平均值

floataverage(floatp[],intn)

{inti;

floatsum=0.0,ave;

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

sum=sum+p[i];

ave=sum/n;

return(ave);

<Bdck<

盛露第8章指針________________________

#defineN10

main()

{floatnum[N],aver;

inti;

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

scanf(n%f,,&num[i]);

aver=average(num,N)

print*"average=%8.2f\n”,aver);

<Bdck<

盛露第8章指針_________________________________

運行情況如下:

102030405060708090100/

average=55.00

程序說明:

本例中,首先定義了一個實型函數(shù)averageO,有

一個形參為實型數(shù)組名P。在函數(shù)體中,把各元素值相加

求出平均值,返回給主函數(shù)。

,Bdck4

盛露第8章指針_________________________________

實參與形參的對應關(guān)系可以有以下幾種:

實參形參

數(shù)組名數(shù)組名

數(shù)組名指針變量

指針變量數(shù)組名

指針變量指針變量

,Bdck4

函露第8章指針

一維數(shù)組的地址可以作為函數(shù)參數(shù)傳遞,二

維數(shù)組的地址也可作函數(shù)參數(shù)傳遞,也可以用指

針孌量或數(shù)組名作形參以接受實參數(shù)組名傳遞來

的地址。在二維數(shù)組名作為函數(shù)的形參時,數(shù)組

名右邊第一個[]可以為空(即使不空也會被忽

略),第二個[]中間不能為空,它是二維數(shù)組的

列數(shù)。

,Bdck4

盛露第8章指針_________________________________

二維數(shù)組指針作函數(shù)參數(shù)舉例。

【例8.16】有一個班,3個學生,各學習4門課,計算總

平均分數(shù),以及第n個學生的成績。

main()

{voidaverage(float*p,intn);

voidsearch(float(*p)[4],intn);

floatscore[3][4]={{65,67,70,60},{80,87,90,81},

{90,99,100,98}};

average(*score,12);search(score,2);

,Bdck4

函露第8章指針

voidaverage(float*p,intn)/*定義求總平均分的函數(shù),

形參是指針變量*/

{float*p_end;

floatsum=0,aver;

p_end=p+n-1;

fbr(;p<=p_end;p++)

sum=sum+(*p);

aver=sum/n;

prints11average=%5.2f\nn,aver);

<Bdck<

盛露第8章指針_________________________________

/*定義求第n個學生成績的函數(shù),形參是二維數(shù)組名*/

voidsearch(floatp[][4],intn)

{inti;

printfV'thescoresofNo,%dare:\n",n);

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

printf(n%5.2f;p[n][i]);

,Bdck4

函露第8章指針

程序運行結(jié)果如下:

average=82.25

thescoresofNO.2are:

90.0099.00100.0098.00

,Bdck4

盛露第8章指針_________________________________

8.9帶參數(shù)的main函數(shù)

帶參數(shù)main函數(shù)一般形式如下:

main(intargc,char*avgv[])

說明:1、main的形參名并不一定非用argc和argv不可,只是

習慣上用這兩個名字。

2、argc用于統(tǒng)計命令行中參數(shù)的個數(shù)(包含C文件名),

argv數(shù)組各元素依次存放命令行各參數(shù)所形成字符串的首

地址。

,Bdck4

盛露第8章指針---------------------------

main函數(shù)是由系統(tǒng)調(diào)用的:當系統(tǒng)處于操作命令

狀態(tài)時,以鍵盤輸入文件名,計算機就運行這個文件

(可執(zhí)行的二進制目標文件)。例如有一源文件名為

cfile.c,經(jīng)過編譯連接后得到的目標文件名為

cflle.exe(在TurboC情況下,執(zhí)行文件的后綴為.exe)。

命令行格式:

C文件名[參數(shù)1[參數(shù)2.......參數(shù)n]]

說明:”C文件名”為所要運行的可執(zhí)行文件名,口表

示這項可以省略,各參數(shù)間用空格隔開。

<Bdck<

盛露第8章指針________________________________

【例8.17]帶參數(shù)main函數(shù)應用舉例。

main(intargc,char*argv[])

{while(argc>l)

{++argv;

printf(n%s\nn,*argv);

-argc;

,Bdck4

函露第8章指針

如果從鍵盤輸入的命令行為:

CfileComputerC_Language/

則輸出為:

Computer

CLanguage

,Bdck4

函露第8章指針

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

一個函數(shù)可以帶回一個整型值、字符值、實型值等,

也可以帶回指針型的數(shù)據(jù),即地址。

返回指針值的函數(shù)一般定義形式為:

類型名*函數(shù)名(參數(shù)表)

例如:

int*a(intx,inty)

,Bdck4

盛露第8章指針_________________________________

【例8.18]編寫一個strchr函數(shù),它的作用是在一個

字符串中找一個指定的字符,返回該字符的地址(庫函

數(shù)中有此函數(shù),今要求自己編寫)。

char*strchr(char*str,charch)

{while(*str++!='\O')if(*str==ch)return(str);

return(0);

<Bdck<

盛露第8章指針_________________________________

main()

{char*pt,ch,line[]=nIloveChina";

ch—c1;

pt=strchr(line,ch);

printf("\nstringstartsataddress%o.\n"Jine);

printf("Firstoccurrenceofchar%cisaddress%o.\n".ch,pt);

printf("Thisisposition%d(staringfrom0)\n”,pt-line);

<Bdck<

遍露第8章指針

運行結(jié)果如下:

stringstartsasaddress177720

FirstoccurrenceofcharCisaddress177727

Thisisposition7(startingfrom0)。

返回指針的函數(shù)是很有用的,許多庫函數(shù)都

是返回指針值的。讀者應很好地掌握它。

,Bdck4

函露第8章指針

8.11函數(shù)指針的定義與引用

8.11.1函數(shù)指針的定義

可以用指針變量指向整型變量、字符串、數(shù)組、也可

以指向一個函數(shù)。一個函數(shù)在編譯時被分配給一個入口

地址,這個入口地址就稱為函數(shù)的指針,即函數(shù)指針。

函數(shù)指針變量定義的一般形式:

數(shù)據(jù)類型標識符(*指針變量名)()

,Bdck4

盛露第8章指針_________________________________

例如:

int(*p)()

指向整型函數(shù)的指針變量。注意*p兩側(cè)的括號不能

省略,否則成了“返回指針值的函數(shù)”To

,Bdck4

盛露第8章指針_________________________________

8.11.2函數(shù)指針變量的賦值

與數(shù)組名代表數(shù)組的起始地址一樣,函數(shù)名代

表函數(shù)的入口地址。

其格式為:函數(shù)指針變量二函數(shù)名;

例如:p=max;

假設(shè)已定義了一個函數(shù)max,則上述賦值語句的

作用是將max函數(shù)的入口地址賦給指針變量p。即

使p指向函數(shù)max。注意函數(shù)名后不能帶括號和參

數(shù)。

<Bdck<

盛露第8章指針_________________________________

8.11.3函數(shù)指針變量的引用

函數(shù)指針變量的引用格式為:

(*函數(shù)指針變量)(實參表列);

例如:若p指向了函數(shù)max,則(*p)(a,b)就相當于max(a,b)。

即用實參a,b調(diào)用函數(shù)max。

注意:對指向函數(shù)的指針變量P,象p+n,p++,p-等

運算是無意義的。

,Bdck4

函露第8章指針

8.11.4函數(shù)指針變量作為函數(shù)的參數(shù)

函數(shù)指針變量常用的用途之一是把指針作為

參數(shù)傳遞到其它函數(shù)。這個問題是C語言應用的

一個比較深入的部分,在本書中只作簡單的介紹,

以便在今后用到時不致感到困惑。進一步的理解

和掌握有待于讀者今后深入的學習和提高。

,Bdck4

函露第8章指針

指向函數(shù)的指針變量作為參數(shù),實現(xiàn)函數(shù)地址的傳

遞,也就是將函數(shù)名傳給形參,其原理可以簡述如下:

有一個函數(shù)(假設(shè)函數(shù)名為sub),它有兩個形參

(xl和x2),定義xl和x2為指向函數(shù)的指針變量。在調(diào)用

函數(shù)sub時,實參用兩個函數(shù)名fl和f2給形參傳遞函數(shù)地

址。這樣在函數(shù)sub中就可以調(diào)用fl和f2函數(shù)了。

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論