版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第8章指針8.1地址、指針與指針變量的基本概念8.2指針變量的定義、賦值和引用8.3數(shù)組指針和指向數(shù)組的指針變量8.4指針與函數(shù)8.5指針的指針8.6動(dòng)態(tài)內(nèi)存分配與指向它的指針變量本章小結(jié)
8.1地址、指針與指針變量的基本概念
8.1.1地址與指針
指針類型數(shù)據(jù)是一種與內(nèi)存相關(guān)的數(shù)據(jù)。要了解指針類型數(shù)據(jù),首先要了解計(jì)算機(jī)的內(nèi)存及內(nèi)存地址這兩個(gè)概念。程序處理的數(shù)據(jù)保存在內(nèi)存中。內(nèi)存是由許多順序排列的存儲(chǔ)單元組成的,一般把存儲(chǔ)器中的一個(gè)存儲(chǔ)單位稱為一個(gè)字節(jié)或內(nèi)存單元。而每一個(gè)內(nèi)存單元都有一個(gè)編號(hào),被稱為“內(nèi)存地址”。對(duì)內(nèi)存數(shù)據(jù)的訪問都通過地址進(jìn)行,程序的變量所占用的內(nèi)存單元的地址就叫變量的指針。使用高級(jí)語(yǔ)言變量掩蓋了內(nèi)存單元、地址等低級(jí)概念,使我們編寫程序時(shí)不必關(guān)心實(shí)現(xiàn)細(xì)節(jié),但實(shí)際上它在程序執(zhí)行的過程中發(fā)揮了巨大的作用。例如,在下面程序段中:
inti;
i=3;
printf("%d",i);當(dāng)程序開始執(zhí)行后,系統(tǒng)首先為變量i分配了地址為2000和2001的存儲(chǔ)單元,如圖8-1所示。然后,當(dāng)執(zhí)行語(yǔ)句“i=3;”時(shí),系統(tǒng)就將二進(jìn)制數(shù)的3存放到變量i所對(duì)應(yīng)的內(nèi)存單元中。最后,在執(zhí)行輸出語(yǔ)句時(shí),系統(tǒng)同樣到該地址處將變量i的值取出并輸出??梢?,程序?qū)ψ兞康乃性L問都與變量的地址有關(guān)。圖8-1變量地址8.1.2指針變量
在C語(yǔ)言中,允許用一個(gè)變量來存放指針,這種變量稱為指針變量。因此,一個(gè)指針變量的值就是某個(gè)內(nèi)存單元的地址或某內(nèi)存單元的指針。例如,將上例中變量i的地址放入另外的變量P中,當(dāng)需要訪問變量i時(shí),可以采用兩種不同的方式訪問。第一種就是之前我們一直使用的通過變量名訪問,即“直接訪問”方式;第二種可以通過訪問變量p,找到i的地址2000,再到2000地址對(duì)應(yīng)的內(nèi)存區(qū)域訪問變量i的值。這種訪問方式被稱為“間接訪問”方式。
8.2指針變量的定義、賦值和引用
8.2.1指針變量的定義
指針變量可以存儲(chǔ)另一個(gè)變量的地址,并可以通過其間接訪問該變量,這就需要在程序中定義指針變量,將其他變量的地址存儲(chǔ)在指針變量中,最終達(dá)到間接訪問變量的目的。
指針變量定義的一般形式為
類型說明符*變量名;其中:
類型說明符:規(guī)定指針變量指向的基類型,即指定指針變量存儲(chǔ)哪種類型數(shù)據(jù)的地址;
*:說明當(dāng)前定義的變量為指針變量;
變量名:指針變量的名稱,遵循C語(yǔ)言對(duì)標(biāo)識(shí)符定義的規(guī)則。
例如:
int*p1; /*p1是指向整型變量的指針變量*/
float*p2; /*p2是指向浮點(diǎn)變量的指針變量*/
char*p3; /*p3是指向字符變量的指針變量*/8.2.2指針變量的賦值
指針變量是一種特殊的變量,對(duì)它的賦值只能賦予其他變量地址。這個(gè)賦值的一般形式為
指針變量=&變量名;
其中:“&”叫做取地址運(yùn)算符,它的作用是返回變量的內(nèi)存起始地址。通過“=”把取出的變量地址賦值給指針變量。通過這種運(yùn)算取得聯(lián)系的指針變量與變量間存在一種“指向”關(guān)系。例如:
inti=100;
int*ip;
ip=&i;
在這里,假設(shè)變量i在內(nèi)存中分配的存儲(chǔ)單元的起始地址是2000,那么當(dāng)變量ip被賦值為i的地址之后,就可以說ip指向i。ip和i的指向關(guān)系可以用圖8-2所示的示意圖來表示。
指針變量與普通變量一樣可以進(jìn)行初始化,例如上例可以改寫如下:
inta;
int*p=&a;圖8-2指針與變量的“指向”關(guān)系在為指針變量進(jìn)行賦值的過程中,需要注意以下問題:
(1)不允許把一個(gè)數(shù)值賦予指針變量,故下面的賦值是錯(cuò)誤的:
int*p;
p=1000;
(2)賦給指針變量的變量地址不能是任意類型數(shù)據(jù)的地址,而只能是與指針變量的基類型具有相同類型的變量的地址。例如,整型變量的地址可以賦給指向整型變量的指針變量,但浮點(diǎn)型變量的地址不能賦給指向整型變量的指針變量。例如,下面的賦值是錯(cuò)誤的:
int*p;
floatx;
p=&x;
(3)被賦值的指針變量前不能再加“?*?”說明符,如寫為?*p=&a也是錯(cuò)誤的。8.2.3引用指針變量所指的值
當(dāng)一個(gè)指針變量指向另一個(gè)變量之后,就可以通過訪問這個(gè)指針變量來間接訪問它所指向的變量,其訪問的一般形式為
*指針變量名;
例如:
inti=200;
int*ip;
printf(“%d\n”,i);
ip=&i;
printf("%d\n",*ip);此程序的輸出結(jié)果如下:
200
200
這段程序中第一個(gè)輸出語(yǔ)句是對(duì)變量i的直接訪問,而第二個(gè)語(yǔ)句是對(duì)變量i的間接訪問,因?yàn)閕p中存放的是變量i的地址,所以ip是指向i的指針變量,在ip前加“?*?”是訪問變量ip中存儲(chǔ)的地址所對(duì)應(yīng)的存儲(chǔ)單元中的數(shù)據(jù)。從中可以看到上面程序段中的兩個(gè)輸出語(yǔ)句雖然訪問變量的方式不同,但結(jié)果相同。
【例8.1】用“間接訪問”方式輸入和輸出變量。
程序如下:
main()
{
inta,b;
int*pointer_1,*pointer_2;
pointer_1=&a; /*將變量a的地址賦值給pointer_1*/
pointer_2=&b; /*將變量b的地址賦值給pointer_2*/
scanf(“%d,%d”,pointer_1,pointer_2);
printf(“%d,%d\n”,*pointer_1,*pointer_2);/*訪問指向變量a、b的指針輸出變量*/
}
說明
(1)在開頭處雖然定義了兩個(gè)指針變量pointer_1和pointer_2,但它們并未指向任何一個(gè)整型變量,只是提供兩個(gè)指針變量,規(guī)定它們可以指向整型變量。語(yǔ)句“pointe_1=&a;pointe_2=&b;”的作用就是使pointer_1指向a,pointer_2指向b,如圖8-3所示。圖8-3指針變量與變量的指向關(guān)系
(2)在scanf語(yǔ)句中,因?yàn)閷?duì)a、b的輸入是通過指針變量進(jìn)行的,而指針變量本身存儲(chǔ)的是變量的地址,所以在輸入時(shí),輸入到列表的表達(dá)式中沒有“&”符號(hào)。
(3)倒數(shù)第二行的?*pointer_1和?*pointer_2就是訪問變量a和b。
思考
(1)如果已經(jīng)執(zhí)行了語(yǔ)句“pointer_1=&a;”,則?&*pointer_1的含義是什么?
(2)*&a的含義是什么?
(3)(pointer_1)++?和pointer_1++?的區(qū)別是什么?
【例8.2】輸入a和b兩個(gè)整數(shù),按先大后小的順序輸出a和b。
程序如下:
main()
{
int*p1,*p2,*p,a,b;
scanf(“%d,%d”,&a,&b);
p1=&a;p2=&b;
if(a<b)
{p=p1;p1=p2;p2=p;} /*p1、p2交換內(nèi)容*/
printf(“\na=%d,b=%d\n”,a,b);
printf("max=%d,min=%d\n",*p1,*p2);
}
說明
(1)“p=p1;”、“p1=p2;”、“p2=p;”三條語(yǔ)句的作用是交換p1和p2變量中的數(shù)據(jù),在交換之前p1和p2分別指向a和b,在交換之后p1和p2分別指向b和a。
(2)在此程序中a、b變量的值是保持不變的。對(duì)比程序:
main()
{
int*p1,*p2
intp,a,b;
scanf(“%d,%d”,&a,&b);
p1=&a;p2=&b;
if(a<b)
{p=*p1;*p1=*p2;*p2=p;}
/*實(shí)際是交換a、b的值*/
printf(“\na=%d,b=%d\n”,a,b);
printf("max=%d,min=%d\n",*p1,*p2);
}
思考
(1)在這段程序中,變量p1和p2的指向是否發(fā)生了變化?
(2)變量a和b的值是否發(fā)生了變化?
綜上所述,指針變量的相關(guān)運(yùn)算符有兩種,即取地址運(yùn)算符“&”和指針運(yùn)算符(或稱間接訪問運(yùn)算符)“?*?”。
需要注意的是,指針運(yùn)算符“?*?”和指針變量定義中的指針說明符“?*?”不是一回事。在指針變量說明中,“?*?”是類型說明符,表示其后的變量是指針類型。而表達(dá)式中出現(xiàn)的“?*?”則是一個(gè)運(yùn)算符,用以表示指針變量所指的變量值。當(dāng)一個(gè)指針變量p指向一個(gè)變量i以后,對(duì)于變量i的訪問方式可以由直接訪問改變?yōu)殚g接訪問。在程序中對(duì)變量的直接訪問通常表現(xiàn)為三種方式,同樣與之對(duì)應(yīng)的間接訪問也有三種方式,如表8-1所示?!纠?.3】輸出兩個(gè)數(shù)中的大者,要求通過直接訪問和間接訪問兩種方式進(jìn)行。
程序如下:
main()
{
inta,b,*pa,*pb;
pa=&a;
pb=&b;
printf(“inputa,b:\n”);
scanf(“%d%d”,&a,p2);
if(*pa>*pb)
/*比較pa和pb所指變量的值,實(shí)際是比較a、b的值*/
printf(“%d”,*pb);
else
printf("%d",b);
}
8.3數(shù)組指針和指向數(shù)組的指針變量
8.3.1指向一維數(shù)組的指針
數(shù)組在內(nèi)存中占有一段連續(xù)的存儲(chǔ)空間,數(shù)組的起始地址即為數(shù)組的指針。C語(yǔ)言中用數(shù)組名表示這塊連續(xù)內(nèi)存單元的首地址。若用一個(gè)指針指向一個(gè)數(shù)組,就可以通過間接訪問讀寫數(shù)組的每個(gè)元素。
下面舉例說明將指針指向一個(gè)數(shù)組的方法。例如:
inta[5]; /*定義a為包含5個(gè)整型數(shù)據(jù)的數(shù)組*/
int*p; /*定義p為指向整型變量的指針*/
p=a;
p=&a[0];
應(yīng)當(dāng)注意,因?yàn)閿?shù)組為int型,所以指針變量也應(yīng)為指向int型的指針變量。數(shù)組的首元素地址即為數(shù)組的起始地址,所以可以用“p=a;”向指針賦數(shù)組名或用“p=&a[0];”數(shù)組首元素地址的方法,使指針指向數(shù)組。賦值的結(jié)果如圖8-4所示,把a(bǔ)[0]元素的地址賦給指針變量p。也就是說,p指向a數(shù)組的第0號(hào)元素。在定義指針變量時(shí)可以賦初值為數(shù)組的起始地址:
int*p=&a[0];
或
int*p=a;
從圖8-4中可以看出有以下關(guān)系:a、&a[0]?均表示數(shù)組a的首地址。應(yīng)該說明的是,p是變量,而a、&a[0]?都是常量。在編程時(shí)應(yīng)予以注意。圖8-4指向一維數(shù)組的指針8.3.2通過指針引用一維數(shù)組元素
1.指針變量的數(shù)學(xué)運(yùn)算
指針在通常情況下是不能進(jìn)行數(shù)值運(yùn)算的,但是如果指針變量p已指向數(shù)組中的一個(gè)元素,則指針可以進(jìn)行以下運(yùn)算:
(1)加、減運(yùn)算。比如,指針p已經(jīng)指向數(shù)組中的某個(gè)元素了,那么p?+?1、p?-?1分別指向當(dāng)前元素的下一個(gè)元素和上一個(gè)元素。
在這里指針的加減運(yùn)算并不是單純將指針變量的值進(jìn)行加減。C語(yǔ)言規(guī)定,p+i實(shí)際上是p+(i*?指針?biāo)笖?shù)據(jù)類型所占的字節(jié)數(shù))。
例如,p指向a[0],p+i指向a[i]?的地址,a+i也得到a[i]?的地址。
(2)指向同一數(shù)組的指針之間可以進(jìn)行減法。比如,p2?-?p1得到兩個(gè)指針?biāo)冈刂g的地址差值。
例如,p2指向a[5],p1指向a[2],p2-p1得到3。
(3)指針的自加、自減運(yùn)算與*運(yùn)算相聯(lián)時(shí)的優(yōu)先級(jí)問題:
由于?++?和?*?同優(yōu)先級(jí),結(jié)合方向自右而左,故?*p++等價(jià)于?*(p++)。
*(p++)與?*(++p)作用不同。若p的初值為a,則?*(p++)等價(jià)于a[0],*(++p)等價(jià)于a[1]。
(*p)++?表示p所指向的元素值加1。
如果p當(dāng)前指向數(shù)組a中的第i個(gè)元素,則?*(p--)相當(dāng)于a[i--],*(++p)相當(dāng)于a[++i],*(--p)相當(dāng)于a[--i],*(p++)相當(dāng)于a[i++]。
2.通過指針訪問數(shù)組元素
引入指針變量后,就可以用下標(biāo)法和指針法兩種方法來訪問數(shù)組元素了。
(1)下標(biāo)法。引用數(shù)組元素可以用下標(biāo)法,即“數(shù)組名稱[下標(biāo)]”。
(2)指針法。指針法即采用?*(a+i)或?*(p+i)的形式,用間接訪問的方法來訪問數(shù)組元素,其中a是數(shù)組名,p是指向數(shù)組的指針變量。
例如,p指向數(shù)組a的首地址,如圖8-5所示。
①p+i和a+i就是a[i]?的地址,或者說它們指向a數(shù)組的第i個(gè)元素。
②*(p+i)或?*(a+i)就是p+i或a+i所指向的數(shù)組元素,即a[i]。例如,*(p+5)或?*(a+5)就是a[5]。
③指向數(shù)組的指針變量也可以帶下標(biāo),如p[i]?與?*(p+i)等價(jià)。圖8-5通過指針引用數(shù)組元素
【例8.4】輸出數(shù)組中的全部元素。(要求:用指針法輸出。)
指針法一:
main()
{
inta[10],i;
for(i=0;i<10;i++)
*(a+i)=i;/*將0~9分別賦值到a[0]~a[9]*/
for(i=0;i<10;i++)
printf("a[%d]=%d\n",i,*(a+i));
}
說明
數(shù)組名即數(shù)組的首地址,數(shù)組名加i即獲得數(shù)組中第i個(gè)元素的地址。
指針法二:
main()
{
inta[10],i,*p;
p=a; /*?p指向數(shù)組a的首地址*/
for(i=0;i<10;i++)
*(p+i)=i; /*通過指針加法將0~9分別賦值到a[0]~a[9]*/
for(i=0,p=a;i<10;i++)
printf("a[%d]=%d\n",i,*(p+i));
}
說明
p是指向數(shù)組的指針,對(duì)p進(jìn)行加i即獲得數(shù)組中第i個(gè)元素的地址。
指針法三:
main()
{
inta[10],i,*p;
for(p=&a[0],i=0;p<a+10;p++,i++)
{
*p=i;
printf(“a[%d]=%d\n”,i,*p);
}
}指針法四:
main()
{
inta[10],i=0,*p;
for(p=a;a<(p+10);a++,i++)
{
*a=i;
printf(“a[%d]=%d”,i,*a);
}
}注意
指針法四是錯(cuò)誤的,因?yàn)閿?shù)組名a代表數(shù)組首元素的地址,它是一個(gè)指針常量,它的值在程序運(yùn)行期間是固定不變的。既然a是常量,所以a++?是無法實(shí)現(xiàn)的。數(shù)組首地址通常不能被賦值。8.3.3字符指針與字符數(shù)組
在實(shí)際應(yīng)用中,字符指針常常用來指向一個(gè)字符數(shù)組、字符常量或字符串。例如:
char*pc;
pc=“China”;
定義字符指針時(shí)可以用字符串常量對(duì)它做初始化。例如:
char*pc=“China”;
我們知道,C語(yǔ)言對(duì)字符串常是以字符數(shù)組的形式存放的。因此,上述語(yǔ)句定義了指向字符的指針pc,其次在內(nèi)存中建立了常量字符串?"China",最后將字符串常量的起始地址存入pc變量中。指針pc與數(shù)組的指向情況如圖8-6所示。圖8-6字符指針與字符數(shù)組
【例8.5】用字符串指針分別指向一個(gè)常量字符串?“China!”?和?“English!”,并輸出這兩個(gè)字符串。
程序如下:
main()
{
char*pc=“China!”; /*指針pc指向字符串常量*/
printf(“%s\n”,pc); /*用%s控制方式輸出pc所指字符串*/
pc=“English!”; /*為pc所指地址處重新賦值*/
printf(“%s\n”,pc);
}
程序運(yùn)行結(jié)果:
China!
English!
說明
pc是指向字符的指針,初始化時(shí)指向了常量字符串?"China!",在后面的語(yǔ)句中,pc被重新賦值指向常量字符串?"English!"。因此,程序輸出結(jié)果得到了兩行不同的輸出。
【例8.6】用字符串指針實(shí)現(xiàn)strcat函數(shù)的功能,完成字符串的連接。
程序如下:
main()
{
char*s1=“Iam”;
char*s2=“astudent.”;
charc[80],*pc;
pc=c;
/*指針pc指向c字符數(shù)組*/
for(;*s1!='\0';s1++,pc++) /*循環(huán)變量s1所指的字符不等于?\0時(shí),即進(jìn)行循環(huán)*/*pc=*s1;
/*將s1所指的值賦值給指針pc指向的地址處*/
for(;*s2!='\0';s2++,pc++)
*pc=*s2;
pc='\0';
printf("%s\n",c);
}
程序運(yùn)行結(jié)果:
Iamastudent.
說明
(1)程序利用兩個(gè)循環(huán)分別將s1和s2指針?biāo)傅淖址群髮懭隿字符數(shù)組,實(shí)現(xiàn)字符串的拼接。
(2)在兩次寫入時(shí),并沒有寫入字符串結(jié)束標(biāo)志?'\0',因此在寫入s2后,需要為c字符數(shù)組添加一個(gè)結(jié)束標(biāo)志。
【例8.7】在輸入的字符串中查找有無字符?‘k’。
程序如下:
main()
{
charst[20],*ps;
inti;
printf(“inputastring:\n”);
ps=st;
scanf(“%s”,ps);
for(i=0;ps[i]!=‘\0’;i++)
/*?ps指針從st首元素開始循環(huán)*/
if(ps[i]==‘k’){
/*如果ps+i所指的元素值等于k,則輸出*/
printf(“thereisa‘k’inthestring\n”);
break;
}
if(ps[i]=='\0')printf("Thereisno'k'inthestring\n");
}8.3.4指向二維數(shù)組的指針
指針可以指向多維數(shù)組,但在應(yīng)用上比較復(fù)雜,較為常用的是指向二維數(shù)組的指針。二維數(shù)組的首地址即為數(shù)組名,也是第一個(gè)元素的地址。在C語(yǔ)言中,二維數(shù)組以行為單位在內(nèi)存中依次存放。
設(shè)有字符型二維數(shù)組num[3][6]如下:
charnum[3][6]={"one","two","three"};
num數(shù)組在內(nèi)存中存儲(chǔ)的情況如圖8-7所示。圖8-7字符二維數(shù)組的存儲(chǔ)設(shè)數(shù)組num的首地址為1000,則數(shù)組第0、1、2行的起始地址分別為1000、1006、1012。C語(yǔ)言允許把一個(gè)字符二維數(shù)組分解為多個(gè)一維數(shù)組來處理。因此數(shù)組num在邏輯上可分解為三個(gè)一維數(shù)組,即num[0]、num[1]、num[2]。每一個(gè)一維數(shù)組中存放一個(gè)字符串,如圖8-8所示。圖8-8二維數(shù)組數(shù)組及數(shù)組元素的地址表示如下:從二維數(shù)組的角度來看,num是二維數(shù)組名,num代表整個(gè)二維數(shù)組的首地址,也是二維數(shù)組0行的首地址,等于1000。num+i代表第i行的首地址。
【例8.8】輸入并輸出字符二維數(shù)組。
程序如下:
main()
{
charday[3][6];
inti;
printf(“inputdayarray:\n”);
for(i=0;i<3;i++)
scanf(“%s”,day[i]);
/*通過訪問二維數(shù)組的每行地址,對(duì)字符串進(jìn)行操作*/
printf(“thedayarrayare:\n”);
for(i=0;i<3;i++)
printf("%s\n",day+i);
}程序運(yùn)行結(jié)果:
inputdayarray:
one↙
two↙
three↙
thedayarrayare:
one
two
three
【例8.9】
編寫競(jìng)賽報(bào)名程序,輸入?yún)①愓咝彰⑴袛嗥渲惺欠裼心惩瑢W(xué)參加。
程序如下:
#definecol30
#definerow6
main()
{
charname[col][row];
charfindname[6];
intnum,i,flag=0;
printf(“inputstudentnum(<30):”);
scanf(“%d”,&num);
printf(“inputallstudentsname:”);
for(i=0;i<num;i++)
scanf(“%s”,name[i]);
printf(“inputfindname:”);
scanf(“%s”,findname);
for(i=0;i<num;i++)
{
if(strcmp(name[i],findname)==0)
/*比較name[i]和findname是否相同*/
{
flag=1;
break;
}
}
if(flag==1)
printf(“Yes,find%s”,findname);
else
printf("No,find%s",findname);
}8.3.5指針數(shù)組
C語(yǔ)言允許定義各種類型的數(shù)組,當(dāng)然也可以定義指針類型數(shù)組,簡(jiǎn)稱指針數(shù)組。指針數(shù)組的所有元素值均為指針。指針數(shù)組是一組有序的指針的集合。指針數(shù)組的所有元素都必須是具有相同存儲(chǔ)類型和指向相同數(shù)據(jù)類型的指針變量。
指針數(shù)組說明的一般形式為
類型說明符*數(shù)組名[數(shù)組長(zhǎng)度]
其中:類型說明符為指針值所指向的變量的類型。
1.字符指針數(shù)組
字符指針數(shù)組是一組指向字符數(shù)組的指針的集合。通常程序里有多個(gè)字符串時(shí),一種常見的做法就是用一個(gè)字符指針數(shù)組指向它們。然后,可以使用循環(huán)語(yǔ)句對(duì)多個(gè)字符串進(jìn)行批量操作,方便用戶編程。
定義一個(gè)字符指針數(shù)組的方法如下:
char*pc[10]
字符指針數(shù)組也可以在定義時(shí)初始化。人們常讓字符指針指向字符串,也常用字符串常量為字符指針數(shù)組中的指針提供初始值。下面是這種用法的一個(gè)例子:
char*country[]={"China","Japan","English"};這里定義了一個(gè)包含3個(gè)字符指針的數(shù)組,同時(shí)建立了3個(gè)字符串常量,讓數(shù)組里的指針分別指向各個(gè)字符串,如圖8-9所示。有了這個(gè)定義后,通過數(shù)組元素country[0]、country[1]和country[2]?等就可以訪問這些字符串了。圖8-9字符指針數(shù)組與一組字符串的指向關(guān)系例如,輸入以上所有字符串:
for(i=0;i<3;i++)
printf(“%s\n”,country[i]);
也可以對(duì)以上字符串進(jìn)行比較或重新輸入:
for(i=0;i<3;i++)
{
if(strcmp(country[i],“Japan”)==0) /*將變量字符串?“apan”?替換為?“Korea”*/
country[i]="Korea";
}
2.指針數(shù)組與二維數(shù)組
指針數(shù)組與二維數(shù)組兩種數(shù)據(jù)結(jié)構(gòu)在編程中可以配合使用。通常二維數(shù)組用來存儲(chǔ)數(shù)據(jù)本身。在C語(yǔ)言中,二維數(shù)組可以以行為單位分解為多個(gè)一維數(shù)組,因此利用指針數(shù)組來存放由二維數(shù)組分解出來的多個(gè)一維數(shù)組的地址,從而通過指針數(shù)組來操作二維數(shù)組中的某一行。
假設(shè)有下面兩個(gè)定義:
intnum[3][3]={1,2,3,4,5,6,7,8,9};
int*pa[3];
pa[0]=num[0];
pa[1]=num[1];
pa[2]=num[2];第一行定義建立了一個(gè)二維(3?×?3)的整型數(shù)組,它占用一片連續(xù)存儲(chǔ)區(qū),數(shù)組的邏輯存儲(chǔ)情況如圖8-10(a)所示。三個(gè)成員數(shù)組里各存一串?dāng)?shù)字。第二行定義一個(gè)包含三個(gè)指針的指針數(shù)組,三條賦值語(yǔ)句的作用是讓數(shù)組里的指針分別指向num數(shù)組的三行。賦值后的情況如圖8-10(b)所示。從這兩個(gè)圖可以清晰地看到兩個(gè)定義的不同。圖8-10二維數(shù)組和指針數(shù)組以上pa指針數(shù)組的應(yīng)用,為num二維數(shù)組建立了另一種以行為整體的聯(lián)系。對(duì)num二維數(shù)組的元素的訪問,可以更為靈活。
例如,用指針法訪問num二維數(shù)組的元素num[i][j]?的常用方法有?*(pa[i]+j)、*(*(pa+i)+j)等。
【例8.10】通過指針數(shù)組訪問二維數(shù)組。
程序如下:
main()
{
intnum[3][3];
int*pa[3];
inti,j;
pa[0]=num[0];
pa[1]=num[1];
pa[2]=num[2];
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
scanf(“%d”,(*(num+i)+j)); /*以行為單位,逐字訪問字符*/
}
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
printf(“%d”,*(pa[i]+j));
printf(“\n”);
}
}
指針數(shù)組在字符串常量編程中更為常用。當(dāng)多個(gè)字符串常量采用二維字符數(shù)組結(jié)構(gòu)存儲(chǔ)時(shí),如果字符串?dāng)?shù)量較多,且數(shù)據(jù)量較大,則需要一塊較大的連續(xù)存儲(chǔ)區(qū)。若將多個(gè)一維數(shù)組分別存儲(chǔ)在不同的存儲(chǔ)區(qū)域,則對(duì)內(nèi)存的要求降低,但是由于多個(gè)一維數(shù)組是一種分散的組織,不便于管理,所以可以使用字符指針數(shù)組分別指向字符串,通過字符指針數(shù)組操作字符串更為簡(jiǎn)便。
【例8.11】用冒泡排序法將5個(gè)國(guó)名按字母順序排列后輸出。
程序如下:
#include“string.h”
main()
{
char*name[]={“CHINA”,“AMERICA”,“AUSTRALIA”,“FRANCE”,“GERMAN”};
inti,j;
char*temp;
for(i=0;i<4;i++)
{
for(j=0;j<4-i;j++)
if(strcmp(name[j],name[j+1])>1)
/*比較相鄰字符串*/
{
temp=name[j];
name[j]=name[j+1];
name[j+1]=temp;
}
}
for(i=0;i<4;i++)
printf("%s\n",name[i]);
}程序運(yùn)行結(jié)果:
AMERICA
AUSTRALIA
CHINA
FRANCE
GERMAN
說明
把各個(gè)國(guó)家名稱的常量字符串分別放在5個(gè)一維數(shù)組中,把這些字符數(shù)組的首地址放在一個(gè)指針數(shù)組里,當(dāng)需要交換兩個(gè)字符串時(shí),只需交換指針數(shù)組相應(yīng)兩個(gè)元素的內(nèi)容(地址)即可,而不必交換字符串本身。這樣可以不必直接交換數(shù)據(jù),從而加速了交換的速度。
3.命令行參數(shù)及其處理
在運(yùn)行程序時(shí),有時(shí)需要將必要的參數(shù)傳遞給主函數(shù)。例如,一個(gè)打開文件的源程序文件名為openfile.c,所產(chǎn)生的可執(zhí)行文件名為openfile.exe,若在命令狀態(tài)下輸入命令:
openfile
這個(gè)程序就會(huì)被裝入并執(zhí)行,但是此處并未指明打開哪個(gè)文件,若想在鍵入命令的同時(shí)指明打開文件的名稱,就必須在鍵入可執(zhí)行程序文件名的同時(shí)輸入目標(biāo)文件名稱,這就需要使用命令行參數(shù)。要編寫能處理命令行參數(shù)的程序,需要了解C語(yǔ)言的命令行參數(shù)機(jī)制。在TurboC中,主函數(shù)的形式參數(shù)為下列形式:
main(intargc,char*argv[])
其中,兩個(gè)特殊的內(nèi)部形參argc和argv是用來接收命令行實(shí)參的,它們是只有main()才能擁有的實(shí)參。argc是整型變量,其作用是保存命令行的參數(shù)個(gè)數(shù);argv是指向命令行字符數(shù)組的指針數(shù)組。這個(gè)數(shù)組里的每個(gè)元素都指向命令行實(shí)參。所有命令行實(shí)參都是字符串,任何數(shù)字都必須由程序轉(zhuǎn)變?yōu)檫m當(dāng)?shù)母袷健O旅嫠o出的簡(jiǎn)單程序說明了命令行實(shí)參的用法。
【例8.12】在屏幕上顯示“Hello”,如果用戶在程序名后直接鍵入自己的名字,則顯示名字。
程序如下:
#include<stdio.h>
main(intargc,char*argv[])
{
if(argc!=2)
{
printf(“youforgottotypeyourname\n”);
exit(0);
}
printf(“Hello%s”,argv[l]);
}若命名該程序?yàn)閚ame.c,可在命令行方式下輸入:
nameMarry
則程序運(yùn)行結(jié)果為:
HelloMarry
說明
(1)以上命令由兩個(gè)參數(shù)組成,第一個(gè)參數(shù)是name,即執(zhí)行程序文件名本身。第二個(gè)參數(shù)是Marry,是要求“問候”的人名。這兩個(gè)參數(shù)分別是一個(gè)一維字符數(shù)組,第一個(gè)一維字符數(shù)組的起始地址放在argv[0]?中,第二個(gè)一維字符數(shù)組的起始地址放在argv[1]?中,如圖8-11所示。圖8-11命令行參數(shù)的用法
(2)
argc接收命令輸入時(shí)參數(shù)的個(gè)數(shù)。因此,在程序中判斷如果argc!=2,則說明用戶輸入的命令不規(guī)范,所以輸出提示信息。如果用戶命令輸入正確,則顯示“Hello”加第二個(gè)參數(shù)的字符串。
8.4指?針?與?函?數(shù)
8.4.1指針作為函數(shù)參數(shù)
1.指針變量作為函數(shù)參數(shù)
函數(shù)的參數(shù)可以是指針類型。它的作用是將一個(gè)變量的地址傳送到另一個(gè)函數(shù)的形參中。這屬于參數(shù)傳遞中的“傳址”方式。
【例8.13】輸入兩個(gè)整數(shù),按大小順序輸出。要求用函數(shù)處理,且用指針類型的數(shù)據(jù)作為函數(shù)參數(shù)。程序如下:
voidswap(int*pa,int*pb)
{
inttemp;
temp=*pa;
*pa=*pb;
*pb=temp;
}
#include<stdio.h>
voidmain()
{
inta,b;
int*p1,*p2;
printf(“inputa,b:”);
scanf(“%d,%d”,&a,&b);
p1=&a;
p2=&b;
if(a<b)
swap(p1,p2);
printf(“theMaxis%d,theMinis%d\n”,a,b);
}
程序運(yùn)行結(jié)果:
inputa,b:3,5↙
theMaxis5,theMinis3
說明
(1)swap是用戶定義的函數(shù),它的作用是交換兩個(gè)變量(a和b)的值。swap函數(shù)的形參pa、pb是指針變量。
(2)程序運(yùn)行時(shí),先執(zhí)行main函數(shù),輸入a和b的值。然后將a和b的地址分別賦給指針變量p1和p2,使p1指向a,p2指向b。接著執(zhí)行if語(yǔ)句,如果a?<?b,則執(zhí)行swap函數(shù)。注意,p1和p2是指針變量作為函數(shù)實(shí)參。在函數(shù)調(diào)用時(shí),將實(shí)參變量的值傳遞給形參變量,因此形參pa的值為&a,pb的值為&b。這時(shí)pa指向變量a,pb指向變量b,如圖8-12(a)所示。
(3)執(zhí)行swap函數(shù)的函數(shù)體,使pa所指的值和pb所指的值互換,其過程分別如圖8-12(b)、(c)、(d)所示。從圖示可以看出,a和b的值已經(jīng)實(shí)現(xiàn)互換。
(4)返回主程序后,將a和b的值輸出,得到交換后的結(jié)果。圖8-12指針作為函數(shù)參數(shù)對(duì)比程序一:
swap(int*pa,int*pb)
{
int*temp;
*temp=*pa;
*pa=*pb;
*pb=temp;
}
#include<stdio.h>
voidmain()
{
inta,b;
int*p1,*p2;
printf(“inputa,b:”);
scanf(“%d,%d”,&a,&b);
p1=&a;
p2=&b;
if(a<b)
swap(p1,p2);
printf("theMaxis%d,theMinis%d\n",a,b);
}
說明
此程序是錯(cuò)誤程序。因?yàn)樵趕wap函數(shù)中,temp變量是指針變量,但沒有指向任何其他變量。因此,在實(shí)現(xiàn)交換過程中,“*temp=*pa;”企圖將pa所指的值即a的值賦給temp所指的變量,但temp并未指向任何一個(gè)存儲(chǔ)單元,所以賦值語(yǔ)句錯(cuò)誤。對(duì)比程序二:
voidswap(intx,inty)
{
inttemp;
temp=x;
x=y;
y=temp;
}
#include<stdio.h>
voidmain()
{
inta,b;
printf(“inputa,b:”);
scanf(“%d,%d”,&a,&b);
if(a<b)
swap(a,b);
printf("theMaxis%d,theMinis%d\n",a,b);
}
說明
在此程序中,swap函數(shù)不能實(shí)現(xiàn)a和b互換。這是因?yàn)?,此處的參?shù)傳遞屬于“傳值”方式,形參的改變不會(huì)影響實(shí)參。
對(duì)比程序三:
swap(int*pa,int*pb)
{
int*temp;
temp=pa;
pa=pb;
pb=temp;
}
#include<stdio.h>
voidmain()
{
inta,b;
printf(“inputa,b:”);
scanf(“%d,%d”,&a,&b);
if(a<b)
swap(&a,&b);
printf("theMaxis%d,theMinis%d\n",a,b);
}
說明
(1)此程序的main函數(shù)中,調(diào)用swap函數(shù)的實(shí)參是a、b變量的地址,即&a和&b。既然實(shí)參傳遞的是指針,那么形參只能是指針變量。
(2)在swap函數(shù)中,交換的是pa和pb的指向,而a和b的值并沒有真正的交換。因此,返回主函數(shù)后再輸出a和b的值,它們的值并沒有按大小重新排列,而是保持不變。
2.?dāng)?shù)組名作為函數(shù)參數(shù)
數(shù)組名就是數(shù)組的指針,因此,數(shù)組名作為函數(shù)參數(shù)時(shí)傳遞的數(shù)據(jù)是整個(gè)數(shù)組的首地址。
數(shù)組名可以作為函數(shù)的實(shí)參,而與其對(duì)應(yīng)的形參應(yīng)為同類型的數(shù)組。例如:
main()
{
intarray[5];
f(array,5);
}
f(intarr[],intn);
{
}………
array是一個(gè)整數(shù)數(shù)組的名稱,作為實(shí)參,對(duì)應(yīng)的形參arr同樣為一個(gè)整數(shù)數(shù)組,但特殊的是,在定義arr數(shù)組時(shí),并沒有定義它的長(zhǎng)度。這是因?yàn)?,?shí)參array傳遞的實(shí)際上是數(shù)組的首地址,即一個(gè)指針,對(duì)應(yīng)的形參arr接收這一地址,那么arr與array指向同一起始地址,如圖8-13所示。因此,操作arr數(shù)組實(shí)際上就是操作array數(shù)組。圖8-13數(shù)組名作為實(shí)參
【例8.14】
編寫函數(shù)求數(shù)組的平均值,要求數(shù)組的值在主函數(shù)中輸入,平均值也在主函數(shù)中輸出。
程序如下:
floataver(float*pa,intn)
{
inti;
floatav,s=0;
for(i=0;i<n;i++)
s=s+*pa++; /*累加數(shù)組元素和*/
av=s/5;
returnav;
}
main()
{
floatscore[5],av;
inti;
printf(“\ninput5scores:\n”);
for(i=0;i<5;i++)
scanf(“%f”,&score[i]);
av=aver(score,5);
printf(“averagescoreis%5.2f”,av);
}
【例8.15】
將數(shù)組a中的n個(gè)整數(shù)按相反順序存放。
方法一:
voidinv(intx[],intn)
{
inttemp,i,j,m=(n-1)/2;
for(i=0;i<=m;i++)
{
j=n-1-i; /*
j,i是所要交換的對(duì)應(yīng)元素的下標(biāo)*/
temp=x[i];x[i]=x[j];x[j]=temp;
}
}
#include<stdio.h>
voidmain()
{
inti,a[10]={3,7,9,11,0,6,7,5,4,2};
printf(“Theoriginalarray:\n”);
for(i=0;i<10;i++)
/*輸出原始數(shù)組的值*/
printf(“%d”,a[i]);
printf(“\n”);
inv(a,10);
printf(“Thearrayhasbeeninverted:\n”);
for(i=0;i<10;i++)
printf("%d",a[i]); /*輸出調(diào)整后的數(shù)組的值*/
}
說明
先將a[0]與a[n-1]對(duì)換,再將a[1]與a[n-2]對(duì)換……直到將a[(n-1/2)]與a[n-int((n-1)/2)]對(duì)換?,F(xiàn)用循環(huán)處理此問題,設(shè)兩個(gè)“位置指示變量”i和j,i的初值為0,j的初值為n-1。將a[i]與a[j]交換,然后使i的值加1,j的值減1,再將a[i]與a[j]交換,直到i=(n-1)/2為止。方法二:
voidinv(int*x,intn) /*形參x為指針變量*/
{
int*p,temp,*i,*j,m=(n-1)/2;
i=x;j=x+n-1;p=x+m;
for(;i<=p;i++,j--)
{temp=*i;*i=*j;*j=temp;} /*
i,j是指向要交換的對(duì)應(yīng)元素的指針*/
return;
}
main()
{
inti,a[10]={3,7,9,11,0,6,7,5,4,2};
printf(“Theoriginalarray:\n”);
for(i=0;i<10;i++)
printf(“%d”,a[i]);
printf(“\n”);
inv(a,10);
printf(“Thearrayhasbeeninverted:\n”);
for(i=0;i<10;i++)
printf(“%d”,a[i]);
printf("\n");
}下面將在函數(shù)中改變實(shí)參數(shù)組值的方法作一歸納。
(1)形參和實(shí)參都用數(shù)組名。例如:
voidf(intx[],intn)
{
}
voidmain()
{
inta[10];
f(a,10);
}………
(2)實(shí)參用數(shù)組名,形參用指針變量。例如:
voidf(int*x,intn)
{
}
voidmain()
{
inta[10];
f(a,10);
}………
(3)形參和實(shí)參都用指針變量。例如:
voidf(int*x,intn)
{
}
voidmain()
{
inta[10],*p=a;
f(p,10);
}………圖8-14數(shù)組名作為實(shí)參與形參的對(duì)應(yīng)關(guān)系
(4)實(shí)參用指針變量,形參用數(shù)組名。例如:
voidf(intx[],intn
)
{
}
voidmain()
{
inta[10],*p=a;
f(p,10);
}………8.4.2指針函數(shù)
指針函數(shù)是指函數(shù)的類型是指針型的。在定義函數(shù)時(shí),每個(gè)函數(shù)都有自己的類型,所謂函數(shù)類型,是指函數(shù)返回值的類型。在C語(yǔ)言中允許一個(gè)函數(shù)的返回值是一個(gè)指針(即地址),這種返回指針值的函數(shù)稱為指針函數(shù)。
指針函數(shù)與非指針函數(shù)定義上的區(qū)別主要在于對(duì)函數(shù)名的聲明上,其定義的一般形式與其他函數(shù)定義相似,即
類型說明符*函數(shù)名(形參表)
{
…/*函數(shù)體*/
}在此定義之中,函數(shù)名之前加了“?*?”,表明這是一個(gè)指針型函數(shù),即返回值是一個(gè)指針。因此在指針函數(shù)的函數(shù)體中必有一個(gè)“return指針;”的返回語(yǔ)句。
例如:
int*ap(intx,inty)
{
…/*函數(shù)體*/
}
【例8.16】利用指針函數(shù)從數(shù)列中選擇最大數(shù),并最終完成選擇排序。
程序如下:
int*max(int*x,intnum)
{
inti,*this=x; /*this指向未排好序的數(shù)列的第一個(gè)元素*/
for(i=1;i<num;i++)
if(*(x+i)>*this)
this=x+i;
returnthis;
}
voidswap(int*first,int*max)
{
inttemp;
temp=*first;
*first=*max;
*max=temp;
}
voidsort(int*pa,intn)
/*pa指向array數(shù)組*/
{
int*pmax,i,j;
for(i=0;i<n;i++)
{
pmax=max(pa+i,n-i); /*調(diào)用求最大值函數(shù),將返回?cái)?shù)組元素中的最大元素
swap(pa+i,pmax); 指針并賦值在pmax中*/
}
}
main()
{
intarray[]={13,5,7,9,40,60,23,77,81,49};
inti;
printf(“Theoriginalarray:”);
for(i=0;i<10;i++)
printf(“%d”,array[i]);
printf(“\n”);
sort(array,10); /*調(diào)用排序函數(shù)*/
printf(“Thearrayhasbeensorted:”);
for(i=0;i<10;i++)
printf("%d",array[i]);
printf("\n");
}
說明
(1)本程序中有三個(gè)函數(shù),即sort、max和swap,分別用于排序、選擇最大值和交換。main函數(shù)在調(diào)用sort函數(shù)時(shí),以array數(shù)組名及數(shù)組長(zhǎng)度10作為實(shí)參,完成參數(shù)傳遞后,sort函數(shù)的形參指針pa指向array數(shù)組的首地址。
(2)sort函數(shù)實(shí)現(xiàn)選擇排序,在每一趟排序過程中選擇最大值的步驟是由函數(shù)max完成的。max函數(shù)是指針函數(shù),比較最大值的算法與“打擂臺(tái)”法基本一致,但在此函數(shù)中,沒有進(jìn)行任何交換,因?yàn)榻粨Q的過程耗時(shí)太多,特別是交換頻繁發(fā)生時(shí),會(huì)導(dǎo)致程序執(zhí)行效率下降。在這里,采用的方法是用this指針始終指向已經(jīng)比較過的數(shù)列中的最大數(shù)。函數(shù)最后返回this指針。8.4.3函數(shù)指針
盡管函數(shù)不是變量,但函數(shù)和變量同樣都要占用一段內(nèi)存單元,函數(shù)也有一個(gè)地址,該地址是編譯器分配給這個(gè)函數(shù)的,這個(gè)地址可以賦給一個(gè)指針,因此指針變量可以指向整型、實(shí)型等變量,也可以指向函數(shù)。指向函數(shù)的指針叫做函數(shù)指針。而函數(shù)的地址實(shí)際上是這個(gè)函數(shù)的入口位置,因此指針指向函數(shù)實(shí)際上是指向函數(shù)對(duì)應(yīng)的程序段的起始地址。正是由于這一點(diǎn),一個(gè)函數(shù)指針可以用來調(diào)用一個(gè)函數(shù)。
1.定義函數(shù)指針變量的一般格式
定義函數(shù)指針變量的一般格式為
函數(shù)類型(*函數(shù)指針標(biāo)識(shí)符)(形參類型說明表);
使用函數(shù)指針時(shí)應(yīng)注意以下幾點(diǎn):
(1)函數(shù)指針與它指向的函數(shù)的參數(shù)個(gè)數(shù)和類型都應(yīng)該是一致的。
(2)函數(shù)指針的類型和函數(shù)的返回值類型也必須是一致的。
2.函數(shù)指針的賦值
函數(shù)名和數(shù)組名一樣代表了函數(shù)代碼的首地址,因此在賦值時(shí),直接將函數(shù)指針指向函數(shù)名即可。
例如:
intfun(intx); /*聲明一個(gè)函數(shù)*/
int(*f)(intx); /*聲明一個(gè)函數(shù)指針*/
f=fun;
3.通過函數(shù)指針調(diào)用函數(shù)
函數(shù)指針是通過函數(shù)名及有關(guān)參數(shù)進(jìn)行調(diào)用的。與其他指針變量相類似,如果指針變量f是指向某整型變量i的指針,則?*f等于它所指的變量。如果?*f是指向函數(shù)func(x)的指針,則?*f就代表這個(gè)強(qiáng)制性指向的函數(shù)func。所以在執(zhí)行“f=func;”之后,(*f)和fun就代表同一函數(shù)。
由于函數(shù)指針指向存儲(chǔ)區(qū)中的某個(gè)函數(shù),因此可以通過函數(shù)指針調(diào)用相應(yīng)的函數(shù)。為實(shí)現(xiàn)這一過程,應(yīng)執(zhí)行以下三步:
(1)定義函數(shù)指針變量。例如:
int(*f)(intx);
(2)對(duì)函數(shù)指針變量賦值。例如:
f=fun;
(3)使用(*f)(參數(shù)表)進(jìn)行函數(shù)調(diào)用。
【例8.17】
利用指針函數(shù)實(shí)現(xiàn)調(diào)用求最大值函數(shù)max。
程序如下:
intmax(intx,inty)
{
if(x>=y)
returnx;
else
returny;
}
main()
{
inti,a,b;
int(*func)(
);
printf(“請(qǐng)輸入a,b的值:”);
scanf(“%d,%d”,&a,&b);
func=max;
/*func指向max函數(shù)*/
printf(“最大值是:”);
printf(“%d”,(*func)(a,b));
/*通過func指針訪問max函數(shù)*/
}
說明
在max函數(shù)中,返回x和y之中的大值。在主函數(shù)中,func指向max函數(shù),通過func調(diào)用max函數(shù)。 8.5指針?的?指?針
指針變量是存儲(chǔ)其他類型變量地址的變量,這里的其他類型也包括指針類型。也就是說,一個(gè)指針變量中存放的地址可以是另一個(gè)指針變量的地址,則稱這個(gè)指針變量為指向指針的指針,也叫做二級(jí)指針。
這種指針的指針與指向數(shù)據(jù)間的關(guān)系如圖8-15所示。圖8-15指針的指針定義二級(jí)指針的一般形式為
數(shù)據(jù)類型**變量標(biāo)識(shí)符;
例如:
int**pp;
其中:**?表示pp是二級(jí)指針;int表示pp中存放指向整型變量指針的地址。指針的指針只能存儲(chǔ)其他指針變量的地址,因此對(duì)指針的指針的一般賦值過程是:
數(shù)據(jù)類型*p1;
數(shù)據(jù)類型**p2;
p2=&p1;二級(jí)指針的數(shù)據(jù)類型定義必須與它所指的指針變量的類型定義相同。要引用二級(jí)指針?biāo)傅臄?shù)據(jù)值,其訪問的一般形式為
**指針變量名;
【例8.18】利用指針的指針編寫程序,判斷在全班同學(xué)中是否有某同學(xué)的名字。
程序如下:
main()
{
char*classmates[]={“WangLin”,“LiQi”,“ZhangMing”,“ChenLu”,“LiLan”};
charname[8];
char**p;
inti,flag=0;
printf("請(qǐng)輸入所要查找的學(xué)生姓名:");
scanf(“%s”,name);
/*name變量用來保存要查找的學(xué)生姓名*/
for(i=0;i<5;i++)
{
p=classmates+i; /*classmates是數(shù)組的首地址,p在循環(huán)中依次指向二維數(shù)組的每一行*/
if(strcmp(*p,name)==0)
{
flag=1;
break;
}
}
if(flag==1)
printf(“%s已報(bào)名\n”,name);
else
printf("%s尚未報(bào)名\n",name);
}
說明
(1)classmates是指針數(shù)組,分別指向5個(gè)常量字符串,如圖8-16所示。classmates是classmates指針數(shù)組的首地址。classmates+i是第i個(gè)常量字符串的起始地址。
(2)定義一個(gè)指針的指針變量p,使它指向指針數(shù)組元素。在循環(huán)中,通過p+i分別得到classmates[0]~classmates[4]?元素的地址。
(3)在訪問常量字符串時(shí),并沒有使用?**p,而使用?*p進(jìn)行訪問。這就是在本例中指針的指針指向的是字符串的緣故。圖8-16指針的指針與指針數(shù)組
【例8.19】
一個(gè)指針數(shù)組的元素指向數(shù)據(jù)的簡(jiǎn)單例子。
程序如下:
main()
{
staticinta[5]={1,3,5,7,9};
int*num[5]={&a[0],&a[1],&a[2],&a[3],&a[4]};
/*指針數(shù)組num的每一個(gè)元素指向?qū)?yīng)的a數(shù)組的每一個(gè)元素*/
int**p,i;
p=num;
for(i=0;i<5;i++)
{printf("%d\t",**p);p++;}
}
說明
(1)num是指針數(shù)組,在初始化時(shí),分別將a數(shù)組的5個(gè)元素的地址賦值給num數(shù)組的對(duì)應(yīng)元素,因此,num數(shù)組的每一個(gè)元素指向?qū)?yīng)的a數(shù)組的每一個(gè)元素。
(2)p是指向指針的指針,p被賦的初值為
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝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ù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 護(hù)理倫理決策圖示
- 學(xué)堂在線 雨課堂 中醫(yī)與診斷-學(xué)做自己的醫(yī)生 期末考試答案
- 護(hù)理溝通中的情緒管理
- 母嬰護(hù)理工具與用品選擇
- 眼科護(hù)理新進(jìn)展與新技術(shù)應(yīng)用
- 告別課件教學(xué)課件
- DSA護(hù)理與患者安全管理
- 如何正確處理鼻腔出血
- 聽見聲音課件
- 致命說服話術(shù)
- 醫(yī)保政策學(xué)習(xí)課件
- 雨課堂學(xué)堂在線學(xué)堂云《科學(xué)研究方法與論文寫作(復(fù)大)》單元測(cè)試考核答案
- 2025浙江省自由貿(mào)易發(fā)展中心招聘工作人員5人(第二批)參考筆試試題及答案解析
- 光學(xué)加工機(jī)械項(xiàng)目可行性分析報(bào)告范文
- 【2025年】天翼云解決方案架構(gòu)師認(rèn)證考試筆試卷庫(kù)下(多選、判斷題)含答案
- GCB發(fā)電機(jī)出口斷路器教育課件
- 柑桔周年管理工作歷第二版課件
- 半導(dǎo)體異質(zhì)結(jié)課件
- Q∕SY 1356-2010 風(fēng)險(xiǎn)評(píng)估規(guī)范
- 高處作業(yè)吊籃安裝驗(yàn)收表(范本模板)
- 美術(shù)第二課堂國(guó)畫教案
評(píng)論
0/150
提交評(píng)論