版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第八章指針表示復(fù)雜的數(shù)據(jù)結(jié)構(gòu)動(dòng)態(tài)分配內(nèi)存有效地使用字符串、數(shù)組在調(diào)用函數(shù)時(shí)能得到多個(gè)返回值能直接處理內(nèi)存地址對設(shè)計(jì)系統(tǒng)軟件是很必要的使用指針可以:§8.1地址和指針的概念如果在程序中定義了一個(gè)變量,在對程序進(jìn)行編譯時(shí),系統(tǒng)會(huì)給這個(gè)變量分配內(nèi)存單元。內(nèi)存區(qū)的每一個(gè)字節(jié)都有一個(gè)編號(hào),這就是"地址"。1、按通過變量名直接找到變量地址,從而存取變量值的方式稱為"直接訪問"方式printf("%d",i);scanf("%d",&i);k=i+j;例如:2、變量i的地址存放在另一個(gè)變量p中,通過變量p獲得變量i的地址,再對變量i進(jìn)行存取變量值的方式稱為"間接訪問"。假設(shè)變量i_pointer用來存放整型變量的地址,可以通過語句:i_pointer=&i;將i的地址(2000)存放到i_pointer中。要存取變量i的值,可以采用間接方式:先根據(jù)變量名i_pointer,得到i的地址(2000),然后從2000、2001字節(jié)取出i的值(3)。3010我們把這種專門用來存放變量地址的變量稱作是指針變量。一個(gè)變量的地址稱為該變量的"指針"。如,地址2000就是變量i的指針。用來存放另一個(gè)變量的地址(指針)的變量,稱為“指針變量”。如i_pointer變量。下面給出指針和指針變量的定義§8.2變量的指針和指向變量的指針變量上圖中箭頭表示"指向"關(guān)系,在程序中用"*"符號(hào)表示"指向"。*i_pointer代表i_pointer所指向的變量i8.2.1定義一個(gè)指針變量定義指針變量的一般形式為基類型*指針變量名;下面都是合法的定義:int*pointer;//pointer是指向int型變量的指針變量char*p,c;//p是指向字符型變量的指針變量,c是字符變量。定義時(shí),如果變量前面沒有*號(hào),則變量不是指針變量。int*pointerint*
是類型pointer是變量名使用取地址運(yùn)算符得到一個(gè)變量的地址,將其賦值給指針變量。inti,j,*pointer_1,*pointer_2;pointer_1=&i;pointer_2=&j;于是:pointer_1指向ipointer_2指向j8.2.2指針變量的初始化
&:取地址運(yùn)算符。#include"stdio.h"voidmain(){inti=5,j=6;
int*i_pointer,*j_pointer;
i_pointer=&i;j_pointer=&j;
printf("i=%d,&i=%d\n",i,&i);printf("i_pointer=%d\n",i_pointer);printf("*i_pointer=%d\n",*i_pointer);
printf("\nj=%d,&j=%d\n",j,&j);printf("j_pointer=%d\n",j_pointer);printf("*j_pointer=%d\n",*j_pointer);}定義指針變量時(shí)要注意兩點(diǎn):在定義指針變量時(shí),指針變量名前面的"*",用來標(biāo)示該變量的類型為指針類型。(2)在定義指針變量時(shí)必須指定基類型。
下面的賦值是錯(cuò)誤的∶
floata;int*pointer_1;pointer_1=&a;
指針變量只能存放與其基類型一致的變量的地址定義指針變量時(shí)要注意兩點(diǎn):指針運(yùn)算的結(jié)果與基類型密切相關(guān)例如,若shortint*p,i;p=&i;則p+1表示使指針往后移動(dòng)2個(gè)字節(jié)若float*p,i;p=&i;則p+1表示使指針往后移動(dòng)4個(gè)字節(jié)#include"stdio.h"voidmain(){charch='a',*ch_pointer=&ch;shortintsint_I=5,*sint_I_pointer=&sint_I;floatfloat_j=6,*float_j_pointer=&float_j;doubledouble_k=4,*double_k_pointer=&double_k;
printf("ch_pointer=%d\n",ch_pointer);printf("ch_pointer+1=%d\n",ch_pointer+1);
printf("\nsint_I_pointer=%d\n",sint_I_pointer);printf("sint_I_pointer+1=%d\n",sint_I_pointer+1);
printf("\nfloat_j_pointer=%d\n",float_j_pointer);printf("float_j_pointer+1=%d\n",float_j_pointer+1);
printf("\ndouble_k_pointer=%d\n",double_k_pointer);printf("double_k_pointer+1=%d\n",double_k_pointer+1);}8.2.2指針變量的引用
指針變量中只能存放指針,不能將一個(gè)整數(shù)(或任何其他非地址類型的數(shù)據(jù))賦給一個(gè)指針變量。兩個(gè)相關(guān)運(yùn)算符:(優(yōu)先級(jí)相同,結(jié)合性為自右而左)
&:取地址運(yùn)算符。*:指針運(yùn)算符(或稱“間接訪問”運(yùn)算符)。取指針變量所指向的變量的值??衫斫鉃椋喝?nèi)容運(yùn)算&和*為一元運(yùn)算符,優(yōu)先級(jí)很高。運(yùn)算時(shí)“從右向左”1.&*pointer等價(jià)于pointer
等價(jià)于
&a
先進(jìn)行*pointer運(yùn)算,得到變量a,再執(zhí)行&運(yùn)算。2.*&a等價(jià)于a等價(jià)于*pointer
即先進(jìn)行&a運(yùn)算,得到a的地址,再執(zhí)行*運(yùn)算在一個(gè)表達(dá)式中,如果*和&緊密相連在一起時(shí),可以理解為:兩個(gè)運(yùn)算相互抵消。若已執(zhí)行pointer=&a;
則#include"stdio.h"voidmain(){inta=7;int*aPtr;
aPtr=&a;
printf("a的地址&a是:%p,指針aPtr為:%p\n\n",
&a,aPtr);
printf("a的值為:%d,指針指向的值*aPtr:%d\n",
a,*aPtr);
printf("\n如果&和*相連出現(xiàn),則等價(jià)于&和*互相抵消\n"
"&*aPtr=%p,*&aPtr=%p",&*aPtr,*&aPtr);}例8.1通過指針變量訪問整型變量&取地址*取內(nèi)容%p:以16進(jìn)制數(shù)整型格式輸出一個(gè)內(nèi)存地址例8.2輸入a和b兩個(gè)整數(shù),按先大后小的順序輸出#include<stdio.h>voidmain(){
inta,b,*p1=&a,*p2=&b,*p;puts("請輸入a,b:");scanf("%d%d",&a,&b);printf("a=%d,b=%d\n",*p1,*p2);
if(a<b)
{p=p1;
p1=p2;
p2=p;}
//交換指針p1,p2
printf("max=%d,min=%d\n",*p1,*p2);printf("a=%d,b=%d",a,b);}p1和p2交換之前p1和p2交換之后#include<stdio.h>voidmain(){inta,b,*p1=&a,*p2=&b,temp,*p=&temp;puts("請輸入a,b:");scanf("%d%d",&a,&b);
printf("a=%d,b=%d\n",*p1,*p2);
if(a<b){*p=*p1;*p1=*p2;*p2=*p;}//交換*p1,*p2
printf("max=%d,min=%d\n",*p1,*p2);printf("a=%d,b=%d",a,b);}指針與函數(shù)指針既然是數(shù)據(jù)類型,自然可以做函數(shù)的參數(shù)和返回值的類型8.2.3變量的指針作為函數(shù)參數(shù)1)地址做為實(shí)參,指針為形參#include<stdio.h>intcube(
int*p
)//形參為指針{intcube; cube=*p**p**p; returncube;}voidmain(){ intn=5,cn; cn=cube(
&n
);//實(shí)參為n的地址
printf("n=%d,n立方=%d",n,cn);}2)指針做為實(shí)參,指針為形參#include<stdio.h>intcube(
int*p
)//形參為指針{ return*p**p**p; }voidmain(){ intn=5,*p=&n,cn; cn=cube(p);//實(shí)參為指針pprintf("n=%d,n立方=%d",n,cn);}3)子函數(shù)直接修改實(shí)參指針?biāo)赶虻膶ο?include<stdio.h>voidcube(
int*p1,int*p2
)//形參為指針{ *p2
=*p1**p1**p1;
/*cube函數(shù)直接修改
*p2對應(yīng)的實(shí)參指針?biāo)赶虻膶ο?/}voidmain(){ intn=5,*p=&n; intcn,
*cnPtr=&cn;
cube(p,cnPtr);//實(shí)參為指針p,cnPtrprintf("n=%d,n立方=%d",*p,*cnPtr);}voidswap(int*x,int*y){inttemp;temp=*x;*x=*y;*y=temp;}main(){voidswap(int*x,int*y);inta,b;a=15;b=8;swap(&a,&b);printf("a=%d,b=%d",a,b);}
voidswap(intx,inty){inttemp;temp=x;x=y;y=temp;}main(){voidswap(intx,inty);inta,b;a=15;b=8;swap(a,b);printf("a=%d,b=%d",a,b);}程序1程序2例8.4:編寫函數(shù)實(shí)現(xiàn)兩數(shù)的互換被調(diào)函數(shù)實(shí)參形參結(jié)果有何不同?主調(diào)函數(shù)簡單變量作函數(shù)參數(shù)圖7-3swap函數(shù)調(diào)用前后參數(shù)變化的示意圖1581581581515881581515a)調(diào)用swap函數(shù)(b)執(zhí)行swap函數(shù)c)從swap函數(shù)返回tempxy
bmain函數(shù)swap函數(shù)①②③aaatemptempxxy
ybb主調(diào)函數(shù)被調(diào)函數(shù)main(){inta,b;a=15;b=8;swap(a,b);printf("a=%d,b=%d",a,b);}voidswap(intx,inty){inttemp;temp=x;x=y;y=temp;}1515ab實(shí)參形參88xyab程序1xyx,y是auto型局部變量,只存在于子函數(shù)中主調(diào)函數(shù)被調(diào)函數(shù)main(){inta,b;a=15;b=8;swap(&a,&b);printf("a=%d,b=%d",a,b);}voidswap(int*x,int*y){inttemp;temp=*x;*x=*y;*y=temp;}&a&a實(shí)參形參&b&bxyab程序2xy15ab8指針變量作函數(shù)參數(shù)用指針變量作函數(shù)參數(shù)實(shí)現(xiàn)兩數(shù)互換函數(shù)的示意圖158815&a&b&a&b15(a)調(diào)用swap函數(shù)
(b)執(zhí)行swap函數(shù)
a
a
b
b
*x
*x
*y
*y
y
y
x
x
&a
&b
main函數(shù)
swap函數(shù)temptemp②①③指針做函數(shù)參數(shù)#include"stdio.h"main(){voidswap(int*x,int*y);inta=15,b=8;printf("執(zhí)行函數(shù)前:&a=%p:a=%d,&b=%p:b=%d\n",&a,a,&b,b);
swap(&a,&b);printf("\n執(zhí)行函數(shù)后:&a=%p:a=%d,&b=%p:b=%d\n",&a,a,&b,b);}voidswap(int*x,int*y){inttemp; printf("\n\t子函數(shù)初值:x=%p:*x=%d,y=%p:*y=%d\n",x,*x,y,*y);
temp=*x;*x=*y;*y=temp;printf("\n\t子函數(shù)終值:x=%p:*x=%d,y=%p:*y=%d\n",x,*x,y,*y);}指針變量作函數(shù)參數(shù)實(shí)際上是:將實(shí)參指針的值傳遞給形參指針,形參指針與實(shí)參指針指向相同的內(nèi)存單元;改變形參指針?biāo)赶虻膬?nèi)存單元里的值,實(shí)際上就是改變實(shí)參指針?biāo)赶虻膬?nèi)存單元里的值。數(shù)組的指針是指數(shù)組的起始地址。數(shù)組元素的指針是指數(shù)組元素的地址。8.3.1指向數(shù)組元素的指針定義一個(gè)指向數(shù)組元素的指針變量,與定義一個(gè)指向變量的指針變量的方法相同。8.3數(shù)組的指針和指向數(shù)組的指針變量例如:inta[10];
/*定義a數(shù)組*/int*p;/*定義p為指向整型變量的指針變量*/p=&a[0];/*使p指向a數(shù)組的第0號(hào)元素*/p=a;/*使p指向a數(shù)組的第0號(hào)元素*/p=&a[0];就是把a(bǔ)[0]元素的地址賦給指針變量p。定義數(shù)組inta[10],數(shù)組名為數(shù)組的首地址,a=&a[0]p=a等價(jià)于p=&a[0]8.3.2通過指針引用數(shù)組元素引用一個(gè)數(shù)組元素,可以用:1.
下標(biāo)法,如a[i]形式
2.
指針法,如*(a+i)或*(p+i)其中a是數(shù)組名,p是指向數(shù)組元素的指針變量,其初值p=a。假設(shè)有一個(gè)a數(shù)組,整型,有10個(gè)元素。要輸出各元素的值有三種方法:#include<stdio.h>voidmain(){inta[3],i; puts("請輸入數(shù)組:");for(i=0;i<3;i++)scanf("%d",&a[i]);printf("\n");
for(i=0;i<3;i++)printf("%5d",
a[i]);}采用下標(biāo)法輸出數(shù)組中的全部元素
#include<stdio.h>#defineN2voidmain(){inta[N],i;for(i=0;i<N;i++)scanf("%d",a+i);printf("\n");
for(i=0;i<N;i++)printf("%d",*(a+i));}(2)通過數(shù)組名計(jì)算數(shù)組元素地址,找出元素的值。(3)用指針變量指向數(shù)組元素#include<stdio.h>#defineN3voidmain(){inta[N],i;int*p=a;puts("請輸入數(shù)組:");for(
i=0;i<N;i++
)scanf("%d",p+i);printf("\n");
for(p=a;p<a+N;p++)printf("%3d",*p);}使用指針變量指向數(shù)組元素應(yīng)注意的問題:1.可改變指針變量的值,不可改變指針常量的值:2.注意指針變量的當(dāng)前值
設(shè)p為指針變量,a為數(shù)組名,則
p++
正確
a++
錯(cuò)誤
a是數(shù)組名,它是數(shù)組首地址,它的值在程序運(yùn)行期間是固定不變的,是常量。#include<stdio.h>#defineN3voidmain(){int*p,i,a[N];
p=a;puts("請輸入數(shù)組:");for(i=0;i<N;i++)scanf("%d",p++);printf("\n");
for(i=0;i<N;i++,p++)printf("%d",*p);}有人編寫出以下程序,是否有錯(cuò)誤?問題出在哪里?問題出在在第一個(gè)for循環(huán)結(jié)束后,p已經(jīng)指向數(shù)組最后一個(gè)元素的下一個(gè)內(nèi)存單元,這些單元里的值是不確定的。解決辦法,在第二個(gè)for循環(huán)之前加一個(gè)賦值語句:p=a;#include<stdio.h>#defineN3voidmain(){int*p,i,a[N];p=a;puts("請輸入數(shù)組:");for(i=0;
i<N;
i++)scanf("%d",p++);for(i=0,
p=a;
i<N;
i++,p++)printf("%3d",*p);}3.p可以指向數(shù)組以后的內(nèi)存單元,如inta[10];p=&a[10](按*(a+10)處理);
但不會(huì)得到預(yù)期的結(jié)果。應(yīng)保證指針指向數(shù)組中有效的元素。1)
p++:使p指向下一元素。2)*p++:++和*同優(yōu)先級(jí),自右而左結(jié)合。等價(jià)于*(p++),p++:先用p,再加1。即先算*p,再使p=p+1。有inta[10],*p;p=a;<=>for(i=0;i<10;i++,p++)printf("%d",*p);for(i=0;i<10;i++)printf("%d",*p++);3)*++p:先使p=p+1,再取*p。以下程序的執(zhí)行結(jié)果為:#include<stdio.h>voidmain(){int*p,i,a[4]={1,2,3,4};p=a;for(i=0;i<3;i++)printf("%3d",*p++);
puts("");for(i=0,p=a;i<3;i++)printf("%3d",*++p);}4)(*p)++:p所指向的元素值加1,即(a[0])++。5)設(shè)p=&a[i],則:*(--p)<=>a[--i],先使p=p-1,再取*p得到a[i-1]。*(p--)<=>a[i--],先取*p得到a[i],再使p-1=>p。*(++p)<=>a[++i],先使p+1=>p,再取*p得到a[i+1]。
設(shè)指針變量p指向數(shù)組a,即p=a8.3.3用數(shù)組名作函數(shù)參數(shù)例如:
voidmain(){voidfunc(intarr[],intn);intarray[10]
;…f(array,10);…}voidfunc(intarr[]
,intn){…}在編譯時(shí)是將arr按指針變量來處理的,相當(dāng)于將函數(shù)f的首部寫成f(int*arr,intn)當(dāng)用數(shù)組名作為函數(shù)參數(shù)時(shí),由于數(shù)組名代表的是數(shù)組首元素地址,因此傳遞的值是地址,所以要求形參為指針變量。例8.8如下圖所示,將數(shù)組a中n個(gè)整數(shù)按相反順序存放p239數(shù)組長度n=10時(shí),正中間的元素下標(biāo):m=4,m=(n-1)/2數(shù)組長度n=11的情況中間元素下標(biāo)m=5例8.8將數(shù)組a中n個(gè)整數(shù)按相反順序存放11m所以:m=(n-1)/2將數(shù)組a中n個(gè)整數(shù)按相反順序存放的算法:確定數(shù)組的中間元素下標(biāo)
m=(n-1)/2;循環(huán)條件:
for(i=0;i<=m;i++)互換規(guī)則:
a[i]=a[n-i-1];#include<stdio.h>voidmain(){voidinv(inta[],intn);voidprintArray(inta[],intn);inta[10]={3,7,9,11,0,6,7,5,4,2};
printf("數(shù)組初值:\n");
printArray(a,10);
inv(a,10);printf("反序后的數(shù)組:\n");
printArray(a,10);}例8.8將數(shù)組a中n個(gè)整數(shù)按相反順序存放//打印數(shù)組函數(shù)定義voidprintArray(inta[],intn){ inti; for(i=0;i<n;i++) printf("%4d",a[i]); printf("\n");}//反序存放數(shù)組函數(shù)定義voidinv(inta[],intn){inti,temp,m; m=(n-1)/2; for(i=0;i<=m;i++){ temp=a[i]; a[i]=a[n-i-1]; a[n-i-1]=temp;}}
#include<stdio.h>voidmain(){voidinv(int*x,intn);voidprintArray(inta[],intn);inta[10]={3,7,9,11,0,6,7,5,4,2};
printf("數(shù)組初值:\n");
printArray(a,10);
inv(a,10);printf("反序后的數(shù)組:\n");
printArray(a,10);}例8.8修改程序,以指針做為函數(shù)形參//打印數(shù)組函數(shù)定義voidprintArray(inta[],intn){ inti; for(i=0;i<n;i++) printf("%4d",a[i]); printf("\n");}//反序存放數(shù)組函數(shù)定義voidinv(int*x,intn){ int*i,*j,temp,m; m=(n-1)/2;
for(i=x,j=i+n-1;i<=x+m;i++,j--){ temp=*i;*i=*j; *j=temp;}}形式參數(shù)形式上是數(shù)組,實(shí)際上是指針變量。歸納起來,如果有一個(gè)實(shí)參數(shù)組,想在函數(shù)中改變此數(shù)組中的元素值,實(shí)參與形參的對應(yīng)關(guān)系有以下4種情況:(1)形參和實(shí)參都用數(shù)組名,如:voidmain()voidf(intx[],intn){inta[10];{……f(a,10);}}(2)實(shí)參用數(shù)組名,形參用指針變量。如:voidmain()voidf(int*x,intn){inta[10];{……f(a,10);}}(3)實(shí)參形參都用指針變量。例如:voidmain()voidf(int*x,intn){inta[10];{…int*p=a;……f(p,10);}}形式參數(shù)形式上是數(shù)組,實(shí)際上是指針變量。(4)實(shí)參為指針變量,形參為數(shù)組名。如:
voidmain()voidf(intx[],intn){inta[10];{…int*p=a;
…
…f(p,10);}}8.3.4多維數(shù)組與指針p245
1.多維數(shù)組元素的地址先回顧一下多維數(shù)組的性質(zhì),可以認(rèn)為二維數(shù)組是"數(shù)組的數(shù)組",例:shortinta[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};則二維數(shù)組a可看成是由3個(gè)一維數(shù)組所組成的。設(shè)二維數(shù)組的首行的首地址為1245008,則124500812450241245040#include"stdio.h"#definePNprintf("\n")voidmain(){inta[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};inti,j;for(i=0;i<3;i++){ for(j=0;j<4;j++)printf("&a[%d][%d]=%d\n",i,j,
&a[i][j]
);PN;}}二維數(shù)組a可看成是由3個(gè)一維數(shù)組所組成的#include"stdio.h"#definePNprintf("\n")voidmain(){inta[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};inti,j;for(i=0;i<3;i++){
printf("a[%d]=%d\n",i,a[i]); for(j=0;j<4;j++)printf("&a[%d][%d]=%d\n",i,j,
&a[i][j]
);PN;}}二維數(shù)組a可看成是由3個(gè)一維數(shù)組所組成的,三個(gè)一維數(shù)組的數(shù)組名分別為a[0],a[1],a[2]a是由a[0],a[1],a[2]組成的一維數(shù)組的數(shù)組名//修改程序?yàn)椋?include"stdio.h"voidmain(){inta[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};inti;
printf("a=%d\n",a);for(i=0;i<3;i++){ printf("a[%d]=%d\n",i,a[i]);}}inta[3][4]定義一個(gè)二維數(shù)組這個(gè)二維數(shù)組可以看成是由a[0],a[1],a[2]三個(gè)元素組成的一維數(shù)組。這個(gè)一維數(shù)組的數(shù)組名是a,是指向數(shù)組元素的指針,代表一維數(shù)組的首地址,值為&a[0]a+n指向數(shù)組中的第n個(gè)元素a+1=&a[1]a+2=&a[2]#include"stdio.h"voidmain(){inta[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};inti;
for(i=0;i<3;i++){ printf("a+%d=%d,&a[%d]=%d\n",i,a+i,i,&a[i]);}}inta[3][4]定義一個(gè)二維數(shù)組這個(gè)二維數(shù)組可以看成是由a[0],a[1],a[2]三個(gè)元素組成的一維數(shù)組。a[0]實(shí)際上是由a[0][0],a[0][1],a[0][2],a[0][3]四個(gè)元素構(gòu)成的一維數(shù)組的數(shù)組名a[0]是指向數(shù)組元素的指針,代表一維數(shù)組的首地址,值為&a[0][0]a[0]+n指向數(shù)組中的第n個(gè)元素a[0]+1=&a[0][1]a[0]+2=&a[0][2]#include"stdio.h"voidmain(){inta[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};inti;
for(i=0;i<3;i++) printf("a[0]+%d=%d,&a[0][%d]=%d\n",i,
a[0]+i,
i,&a[0][i]
);}a[0]+1:對應(yīng)第0行第1列的地址a[1]+1:對應(yīng)第1行第1列的地址,a[2]+1:對應(yīng)第2行第1列的地址如圖10.22所示。二維數(shù)組名a代表數(shù)組a的首元素的地址,數(shù)組a的每一個(gè)元素都是一個(gè)長度為4的一維數(shù)組,故a+1:代表下標(biāo)為1的元素的地址,對應(yīng)數(shù)組名a[1]a+2:代表下標(biāo)為2的元素的地址,對應(yīng)數(shù)組名a[2]一維數(shù)組名a[0]代表數(shù)組a[0]的首元素的地址&a[0][0]一維數(shù)組名a[1]代表數(shù)組a[1]的首元素的地址&a[1][0]一維數(shù)組名a[2]代表數(shù)組a[2]的首元素的地址,&a[2][0]故#include"stdio.h"voidmain(){inta[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};printf("a=%p\n",a);printf("*a=%p\n",*a);printf("a[0]=%p\n",a[0]);printf("&a[0]=%p\n",&a[0]);printf("&a[0][0]=%p\n\n",&a[0][0]);}a與a[0]的值雖相同,但由于指針類型不同:
a:
二維數(shù)組名,指向行a[0];a[0]:一維數(shù)組名,指向列元素a[0][0]。故a+1≠a[0]+1對一維數(shù)組inta[N]:a[i]表示a數(shù)組的第i個(gè)元素的值對二維數(shù)組inta[N][M]:a[i]是一個(gè)一維數(shù)組名,是一個(gè)地址在行指針前加一個(gè)*,行指針就轉(zhuǎn)換為列指針*a=a[0]:指向第0列的指針在列指針前面加&,列指針就成為行指針
&a[0]=a:指向第0行的指針∵a[i]<=>*(a+i)∴a[i]+j<=>*(a+i)+j<=>&a[i][j]∴*(a[i]+j)<=>*(*(a+i)+j)<=>a[i][j]由上可看出:a+1:1代表一行中全部元素所占字節(jié)數(shù)8a[i]+1:1代表一列元素所占字節(jié)數(shù)2第i行第j列的元素的地址可表示為:a[i]+j表示形式含義地址a
二維數(shù)組名,即0行首地址2000*(a+0),*a,a[0]0行0列元素地址2000a+1,&a[1]1行首地址2008*(a+1),a[1]1行0列元素a[1][0]的地址2008*(a+1)+2,a[1]+2,&a[1][2]1行2列元素a[1][2]的地址2012*(a[1]+2),*(*(a+1)+2),a[1][2]1行2列元素a[1][2]的值元素值為13直接使用二維數(shù)組下標(biāo)#include"stdio.h"voidmain(){shortinta[3][4]={{0,1,2,3},{10,11,12,13},{20,21,22,23}};inti,j;for(i=0;i<3;i++){ printf("\n"); for(j=0;j<4;j++) printf("%p:%d\n",&a[i][j],a[i][j]);}}以一維數(shù)組名為指針#include"stdio.h"voidmain(){shortinta[3][4]={{0,1,2,3},{10,11,12,13},{20,21,22,23}};inti,j;for(i=0;i<3;i++){ printf("\n"); for(j=0;j<4;j++) printf("%p:%d\n",a[i]+j,*(a[i]+j));}}以二維數(shù)組名為指針#include"stdio.h"voidmain(){shortinta[3][4]={{0,1,2,3},{10,11,12,13},{20,21,22,23}};inti,j;for(i=0;i<3;i++){ printf("\n"); for(j=0;j<4;j++) printf("%p:%d\n",*(a+i)+j,*(*(a+i)+j));}}以下程序是否有誤?#include"stdio.h"voidmain(){shortinta[3][4]={{0,1,2,3},{10,11,12,13},{20,21,22,23}};inti,j;for(i=0;i<3;i++){ printf("\n"); for(j=0;j<4;j++) printf("%p:%d\n",(a+i)+j,*(*(a+i)+j));}}2.指向多維數(shù)組元素的指針變量(1)指向數(shù)組元素的指針變量例用指針變量輸出二維數(shù)組元素的值
#include"stdio.h"voidmain(){inta[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};inti,j;
int*p=&a[0][0];for(i=0;i<3;i++) {printf("\n"); for(j=0;j<4;j++) printf("%2d",
*(p+i*4+j)); }}
a[i][j]在數(shù)組a[m][n]中的相對位置的計(jì)算:
i*n+j
/*之前有i行,每行有n個(gè);之前還有j個(gè)*/
故a[i][j]的值可表示為*(p+i*n+j)
例如,數(shù)組a[3][4]中的a[2][3]的值可表示為:*(p+2*4+3)即*(p+11)如圖如果修改程序如下,結(jié)果如何?#include"stdio.h"voidmain(){inta[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};inti,j;
int*p=a;for(i=0;i<3;i++) {printf("\n"); for(j=0;j<4;j++) printf("%2d",
*(p+i*4+j)); }}
--------------------Configuration:c11-Win32Debug-------:errorC2440:'initializing':cannotconvertfrom'int[3][4]'to'int*'Typespointedtoareunrelated;conversionrequiresreinterpret_cast,C-stylecastorfunction-stylecast執(zhí)行cl.exe時(shí)出錯(cuò).c11.exe-1error(s),0warning(s)a與a[0]的值雖相同,但由于指針類型不同:
a:
二維數(shù)組名,指向行a[0];a[0]:一維數(shù)組名,指向列元素a[0][0]。故a+1≠a[0]+1對一維數(shù)組inta[N]:a[i]表示a數(shù)組的第i個(gè)元素的值對二維數(shù)組inta[N][M]:a[i]是一個(gè)一維數(shù)組名,是一個(gè)地址a是行指針,*a=a[0]指向第0列的指針,也就是說,a是指向指針的指針變量。a[0]是列指針,a[0]是指向整型變量的指針變量2.指向多維數(shù)組元素的指針變量(1)指向數(shù)組元素的指針變量例8.11用指針變量輸出二維數(shù)組元素的值
#include"stdio.h"voidmain(){int
a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};inti,j;
int(*p)[4]
=a;for(i=0;i<3;i++) {printf("\n"); for(j=0;j<4;j++) printf("%2d",
*(*(p+i)+j)); }}
(2)指向一維數(shù)組的指針變量例8.13輸出二維數(shù)組任一行任一列元素的值#include"stdio.h"main(){inta[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};int(*p)[4]=a;inti,j;printf("i(0-2):");scanf("%d",&i);printf("j(0-3):");scanf("%d",&j);printf("a[%d][%d]=%2d",i,j,*(*(p+i)+j));}①inta[4];
//a為數(shù)組名,有4個(gè)整型元素②
int(*p)[4];
//(*p)為數(shù)組名,有4個(gè)整型元素這4個(gè)元素分別為:
(*p)[0],(*p)[1],(*p)[2],(*p)[3]圖8.24(*p)=a[0],(*(p+1))=a[1],(*(p+2))=a[2],(*(p+3))=a[3],對應(yīng)于a[0][0]…a[0][3],a是二維數(shù)組名,故p是行指針,指向二維數(shù)組的每一行?!?(p+i)+j
是a數(shù)組第i行第j列元素的地址。即*(*(p+i)+j)
是a[i][j]
的值。對int(*p)[4];的理解:圖8.24圖8.253.用指向數(shù)組的指針作函數(shù)參數(shù)例8.14有一個(gè)班,3個(gè)學(xué)生,各學(xué)4門課,計(jì)算總平均分?jǐn)?shù)以及第n個(gè)學(xué)生的成績。p2521)用指向數(shù)組的指針作函數(shù)參數(shù)。
2)定義函數(shù)average求總平均成績
3)定義函數(shù)search找出并輸出第i個(gè)學(xué)生的成績。voidaverage
(
float*p,intn
){float*p_end;
floatsum=0,aver;
p_end=p+n-1;
for(;p<=p_end;p++)
sum=sum+(*p);
aver=sum/n;
printf("average=%5.2f\n",aver);}voidsearch(
float(*p)[4],intn
){
inti;
printf("no.%d
:\n",n);
for(i=0;i<4;i++)
printf("%5.2f",*(*(p+n)+i));}#include"stdio.h“voidmain(){voidaverage(float*p,intn);voidsearch(float(*p)[4],intn);floatscore[3][4]={{65,67,70,60},
{80,87,90,81},
{90,99,100,98}};/*求12個(gè)分?jǐn)?shù)的平均分*/average(*score,12);/*求序號(hào)為2的學(xué)生的成績*/search(score,2);}例8.15在上題基礎(chǔ)上,查找有一門以上課程不及格的學(xué)生,打印出他們的全部課程的成績。
#include<stdio.h>voidmain(){void
search(float(*p)[4],intn);/*函數(shù)聲明*/floatscore[3][4]={{65,57,70,60},{58,87,90,81},{90,99,100,98}};
search(score,3);}voidsearch(float(*p)[4],intn){inti,j,flag;for(j=0;j<n;j++){flag=0;for(i=0;i<4;i++)if(*(*(p+j)+i)<60)
flag=1;if(flag==1){printf("no.%dfails,hisscoresare:\n",j+1);
for(i=0;i<4;i++)printf("%5.1f",*(*(p+j)+i));
printf("\n");
}}}
程序運(yùn)行結(jié)果如下:no.1fails,hisscoresare:65.057.070.060.0no.2fails,hisscoresare∶58.087.090.081.0§8.4字符串與指針8.4.1字符串的表示形式
例8.16定義一個(gè)字符數(shù)組,對它初始化,
然后輸出該字符串
#include<stdio.h>voidmain(){charstring[]="ilovechina!";printf("%s\n",string);}(1)用字符數(shù)組存放一個(gè)字符串,然后輸出該字符串。(2)用字符指針指向一個(gè)字符串
可以不定義字符數(shù)組,而定義一個(gè)字符指針。用字符指針指向字符串中的字符。例8.17定義字符指針#include<stdio.h>voidmain(){char*string="ilovechina!";
printf("%s\n",string);}其中,char*string="ilovechina!";<=>char*string;string="ilovechina!";是把字符串首地址賦給string。不是把字符串"ilovechina!"賦給*string。例8.18將字符串a(chǎn)復(fù)制為字符串b
#include<stdio.h>voidmain(){chara[]="iamaboy.",b[20];inti;for(i=0;*(a+i)!='\0';i++)*(b+i)=*(a+i);*(b+i)='\0';printf("stringais:%s\n",a);printf("stringbis:");for(i=0;b[i]!='\0';i++)printf("%c",b[i]);}對字符串中字符的存取,可以用下標(biāo)方法,也可以用指針方法例8.18用指針變量來處理例8.17問題。p258#include"stdio.h"#include"string.h"voidmain(){chara[]="GuangZhouHEMC.",b[40];char*p1=a,*p2=b;for(;*p1!='\0';p1++,p2++)*p2=*p1;*p2='\0';printf("stringbis:");puts(a);printf("stringbis:");p2=b;
puts(p2);}程序必須保證使p1和p2同步移動(dòng)。8.4.2字符指針作函數(shù)參數(shù)#include<stdio.h>voidmain(){voidcopy_string(charfrom[],charto[]);chara[]="";charb[]=".";printf("字符串a(chǎn)=%s\n字符串b=%s\n",a,b);printf("\n拷貝字符串a(chǎn)至b:\n");copy_string(a,b);printf("\n字符串a(chǎn)=%s\n字符串b=%s\n",a,b);}voidcopy_string(charfrom[],charto[]){inti=0;while(from[i]!='\0'){to[i]=from[i];i++;}to[i]='\0';}(1)用字符數(shù)組名作參數(shù)(2)
用字符指針變量
作參數(shù)#include<stdio.h>voidmain(){voidcopy_string(char*from,char*to);chara[]="";charb[]=".";printf("字符串a(chǎn)=%s\n字符串b=%s\n",a,b);printf("\n拷貝字符串a(chǎn)至b:\n");copy_string(a,b);printf("\n字符串a(chǎn)=%s\n字符串b=%s\n",a,b);}voidcopy_string(char*from,char*to){
while(*to++=*from++);}voidcopy_string(char*from,char*to){for(;*from!='\0';from++,to++)*to=*from;*to='\0';}(3)copy_string函數(shù)體還可寫成如下形式:{while((*to=*from)!='\0'){to++;from++;}}{while((*to++=*from++)!='\0');}{while(*from!='\0‘)*to++=*from++;*to='\0';}while(*to++=*from++);將*from賦給*to,如果賦值后的*to值等于'\0',則循環(huán)終止('\0'已賦給*to)
while語句也可以改用for語句:for(;(*to++=*from++)!='\0';);或for(;*to++=*from++;);也可用指針變量,函數(shù)copy_string可寫為voidcopy_string(charfrom[],charto[]){char*p1,*p2;p1=from;p2=to;
while((*p2++=*p1++)!='\0');}8.4.3對使用字符指針變量和字符數(shù)組的討論雖然用字符數(shù)組和字符指針變量都能實(shí)現(xiàn)字符串的存儲(chǔ)和運(yùn)算,但它們二者之間是有區(qū)別的,不應(yīng)混為一談,主要有以下幾點(diǎn):(1)字符數(shù)組由若干個(gè)元素組成,每個(gè)元素中放一個(gè)字符,而字符指針變量只能存放一個(gè)字符的地址(字符串第1個(gè)字符的地址)。(2)賦值方式。對字符數(shù)組除了在定義時(shí),其它時(shí)候不能整體賦值。指針可以整體賦值,但所賦的不是字符而是首字符的地址。charstr[14];str="ilovechina!";錯(cuò)誤而對字符指針變量,可以采用下面方法賦值:char*a;a="ilovechina!";正確(3)如果定義了一個(gè)字符數(shù)組,它有確定的值;定義一個(gè)字符指針,若未對其賦值,則其值是個(gè)不可預(yù)料的值。如:charstr[10];scanf(“%s”,str);
//正確。而常有人用下面的方法,目的是想輸入一個(gè)字符串,雖然一般也能運(yùn)行,但這種方法是危險(xiǎn)的:
char*a;scanf(“%s”,a);//危險(xiǎn),a無初值應(yīng)當(dāng)這樣:char*a,str[10];a=str;scanf("%s",a);(5)指針變量的值是可以改變的,數(shù)組名除了作形參,值不能被改變,是個(gè)指針常量。如:例8.20改變指針變量的值#include<stdio.h>voidmain(){char*a="ilovechina!";a=a+7;printf("%s",a);}下面是錯(cuò)的:char
str[]={"ilovechina!"};str=str+7;//錯(cuò)誤printf("%s",str);8.5指向函數(shù)的指針8.5.1用函數(shù)指針變量調(diào)用函數(shù)
可以用指針變量指向整型變量、字符串、數(shù)組,也可以指向一個(gè)函數(shù)。一個(gè)函數(shù)在編譯時(shí)被分配給一個(gè)入口地址。這個(gè)函數(shù)的入口地址就稱為函數(shù)的指針。#include<stdio.h>void
main(){intmax(int,int);
inta,b,c;
scanf("%d,%d",&a,&b);c=max(a,b);
printf("a=%d,b=%d,max=%d",a,b,c);}intmax(intx,inty){returnx>y?x:y;}例:8.22求兩數(shù)中的大數(shù)p267int(*p)(int,int);p=max;c=(*p)(a,b);int(*p)()——p是指向的函數(shù)的指針變量,函數(shù)的返回值為整型。int*p()——p是函數(shù)名,函數(shù)的返回值是指向整型值的指針。故*p兩側(cè)的括弧不可省略,表示p先與*結(jié)合,是指針變量,然后再與后面的()結(jié)合,表示此指針變量指向函數(shù),這個(gè)函數(shù)值(即函數(shù)返回的值)是整型的。#include<stdio.h>voidmain(){intmax(int,int);/*函數(shù)聲明*/intmin(int,int);/*函數(shù)聲明*/intadd(int,int);/*函數(shù)聲明*/voidprocess(int,int,int(*fun)());/*函數(shù)聲明*/
inta,b;
printf("enterab:");scanf("%d%d",&a,&b);
printf("max=");process(a,b,max);
printf(“min=”);
process(a,b,min);
printff(“sum=”);
process(a,b,add);}8.5.2用指向函數(shù)的指針作函數(shù)參數(shù)例8.23設(shè)一個(gè)函數(shù)process,在調(diào)用它的時(shí)候,每次實(shí)現(xiàn)不同的功能。輸入a和b兩個(gè)數(shù),第一次調(diào)用process時(shí)找出a和b中大者,第二次找出其中小者,第三次求a與b之和。
intmax(intx,inty)/*函數(shù)定義*/{returnx>y?x:y);}intmin(intx,inty)/*函數(shù)定義*/
{returnx>y?y:x);}intadd(intx,inty)/*函數(shù)定義*/{returnx+y;}voidprocess(intx,inty,int(*fun)(int,int)){printf("%d\n",(*fun)(x,y););}8.6返回指針值的函數(shù)一個(gè)函數(shù)可以帶回一個(gè)整型值、字符值、實(shí)型值等,也可以帶回指針型的數(shù)據(jù),即地址。其概念與以前類似,只是帶回的值的類型是指針類型而已。這種帶回指針值的函數(shù),一般定義形式為類型名*函數(shù)名(參數(shù)表列);例如:int
*a(intx,inty);例8.24有若干個(gè)學(xué)生的成績(每個(gè)學(xué)生有4門課程),要求在用戶輸入學(xué)生序號(hào)以后,能輸出該學(xué)生的全部成績。用指針函數(shù)來實(shí)現(xiàn)。#include<stdio.h>voidmain(){floatscore[][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}};float*search(float(*pointer)[4],intn);float*p;inti,m;printf("enterthenumberofstudent:");scanf("%d",&m);printf("thescoresofno.%dare:\n",m);p=search(score,m);for(i=0;i<4;i++)printf("%5.2f\t",*(p+i));}float*search(float(*point)[4],intn){float*pt;pt=*(point+n);return(pt);}8.7指針數(shù)組和指向指針的指針8.7.1指針數(shù)組的概念一個(gè)數(shù)組,若其元素均為指針類型數(shù)據(jù),稱為指針數(shù)組,也就是說,指針數(shù)組中的每一個(gè)元素都相當(dāng)于一個(gè)指針變量。一維指針數(shù)組的定義形式為類型名數(shù)組名[數(shù)組長
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(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ǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 函數(shù)的奇偶性的說課稿
- 上市公司員工購房合同范本
- 轉(zhuǎn)口貿(mào)易合同中運(yùn)輸條款
- 辦公大樓浮雕施工合同
- 物業(yè)公司財(cái)務(wù)內(nèi)控手冊
- 城市公園綠化招投標(biāo)報(bào)名表
- 活動(dòng)攝像租賃簡易合同
- 餐飲KTV音響系統(tǒng)設(shè)備協(xié)議
- 航運(yùn)服務(wù)招投標(biāo)專用合同條款
- 體育館消防工程合同
- 勘察設(shè)計(jì)單位管理制度模版
- 2024年中國鐵塔湖北分公司招聘筆試參考題庫含答案解析
- 生產(chǎn)設(shè)備搬遷方案
- 住院病案首頁數(shù)據(jù)填寫質(zhì)量規(guī)范
- 永椿化工新材料有限公司 年產(chǎn) 800 噸鄰三氟甲基苯甲酰氯系列產(chǎn)品、1500 噸 2,6- 二氟苯甲酰胺系列產(chǎn)品、500 噸叔丁基二甲基氯硅烷、500 噸 3-氨基-2-溴-5-氟苯甲酸甲酯等產(chǎn)品項(xiàng)目環(huán)境影響報(bào)告書
- GB/T 21837-2023鐵磁性鋼絲繩電磁檢測方法
- 給高二孩子的一封信
- 廚房衛(wèi)生教案-勞動(dòng)課教學(xué)設(shè)計(jì)
- 鍍鋅板通風(fēng)管工程施工方案
- 助產(chǎn)職業(yè)生涯規(guī)劃書
- 體外診斷試劑注冊申報(bào)資料模板-穩(wěn)定性研究資料
評(píng)論
0/150
提交評(píng)論