




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
會計學(xué)1C指針和引用實用概述
指針是C++語言的重要概念,利用指針可以高效而簡潔的處理數(shù)據(jù),有些操作不借用指針是無法完成的(如直接訪問內(nèi)存地址、動態(tài)分配內(nèi)存)。因此指針成為靈活編程的重要工具。但萬事有利就有弊,在程序中不加節(jié)制的濫用指針將造成程序的數(shù)據(jù)流混亂,可讀性下降等問題。所以在使用指針時要多一分小心。第1頁/共81頁預(yù)備知識
內(nèi)存就是內(nèi)部存儲器,由存儲單元組成。它的特點是存儲單元是線性連續(xù)的。存儲單元的最小單位是字節(jié)。···············
正如我們的住房都有門牌號碼一樣,為了訪問內(nèi)存中的某個存儲單元,我們也要為它編號,這種編號稱為內(nèi)存地址。通過地址我們就能夠訪問該地址所標(biāo)示的存儲單元?!ぁぁぁぁぁぁぁ?123203地址內(nèi)容45第2頁/共81頁
在程序中定義了一個變量,這個變量在內(nèi)存中就要占用一定大小的空間,通常這個空間的大小就由這個變量的類型決定。變量在內(nèi)存中總是占用幾個連續(xù)的字節(jié),開始字節(jié)的地址就是變量的地址。inti;
charch;
floatf1;
i=10;
ch=‘A’;
f1=3.14;3.14‘A’10地址變量2000200420052008ichf14字節(jié)1字節(jié)4字節(jié)第3頁/共81頁什么是指針
指針就是變量的地址。與此對應(yīng),在C++語言中使用一種專門的變量---指針變量來存放另一變量的地址。也就是說,指針變量是存放地址數(shù)據(jù)的變量,它的值應(yīng)該是某個變量的地址。指針變量變量地址(指針)變量變量的值指向地址存入指針變量第4頁/共81頁
一般來說,指針變量只能存放某一種數(shù)據(jù)類型的變量地址,由此可以將指針變量劃分為整型指針變量、實型指針變量、字符型指針變量等等。
整型指針變量只能存放整型變量的地址。
實型指針變量只能存放實型變量的地址。
字符型指針變量只能存放字符型變量的地址。
當(dāng)把變量的地址存入指針變量后,我們就可以說這個指針指向了該變量。指針變量pi2000變量i變量i的值指向地址2000第5頁/共81頁指針的定義
指針定義的結(jié)構(gòu)形式如下:
數(shù)據(jù)類型名*指針變量名如:int*ptr1,*ptr2;float*ptr3;char*ptr4;在定義指針時要注意以下幾個問題:
1。指針變量名前面的星號“*”不能省略,如果寫成
int*ptr1,ptr2;則ptr2被定義為整型變量而非指針變量。2。定義中的星號“*”表示所定義的變量是指針變量,但指針變量名是ptr1、ptr2,而非*ptr1、*ptr2。第6頁/共81頁3。指針變量只能指向定義時所規(guī)定類型的變量。如ptr1只能指向整型變量,ptr4只能指向字符型變量。4。定義指針變量后,并未確定該變量指向何處。也就是說變量的值是不確定的。在引用指針變量前,必須首先讓它確定一個變量,這一點非常重要。第7頁/共81頁指針的賦值
指針的賦值運算就是把地址值賦值給指針變量。指針的賦值運算可以是以下幾種方式:
1。使用取地址運算符&。如:
inti,a[5],*ptr;
ptr=&i;ptr=&a[1];2。把指針變量的值賦值給另一個指針變量。如:
inti,*ptr1=&i,*ptr2;ptr2=ptr1;可不可以把a(bǔ)賦值給ptr,即ptr=a;?可以!a即為數(shù)組的首地址。ptr=a;等價于ptr=&a[0];第8頁/共81頁3。給指針變量賦值為賦號常量NULL,如:
int*ptr;ptr=NULL;
實際上NULL是一個空指針,這樣的指針不指向任何變量。為了避免指針變量的非法引用,我們一般要給沒有被初始化的指針變量賦值為NULL作為標(biāo)志。4。把指針變量賦值為0。如:int*ptr=0;
這里的0等價于NULL,值0是唯一能夠直接賦值給指針變量的整數(shù)值。第9頁/共81頁&(取地址運算)和*(引用運算)
地址運算符&的作用是取變量的地址,如:&i表示求變量i的地址。
引用運算符*的作用是取指針?biāo)赶蜃兞康膬?nèi)容,例如:*ptr表示求指針ptr所指向變量的內(nèi)容。&運算和*運算是一對互逆運算。20003指針ptr2000iptr指向了i變量*ptr表示取所指向變量i的值,即3inti=3,*ptr;
ptr=&i;*ptr=15;?20002000i指針ptr*ptr=15等價于i=15,因此改變了變量i的值。15第10頁/共81頁例:
voidmain()
{charch=‘A’,*ch_ptr;
ch_ptr=&ch;
cout<<“ch=”<<ch<<endl;
cout<<“*ch_ptr=”<<*ch_ptr<<endl;
*ch_ptr=‘X’;
cout<<“ch=”<<ch<<endl;
cout<<“*ch_ptr=”<<*ch_ptr<<endl;
cout<<“ch的地址是”<<ch_ptr;輸出結(jié)果ch=A*ch_ptr=Ach=X*ch_ptr=Xch的地址是0xFFF5第11頁/共81頁指針的+、-運算
指針可以加上或減去一個整數(shù),指針的這種運算的意義和通常的數(shù)值的加減運算的意義不同。
指針的加減運算分為兩種:一種是指針與整型值的加減運算,一種是指針與指針的減運算。structstudent{intnumber;charname[4];}student*pst;pst=pst+1;pst第12頁/共81頁指針運算是地址的運算(T*px)
一:px+n,px-n——將指針從當(dāng)前位置向前或向后移動n個數(shù)據(jù)單位,而不是n個字節(jié)。這取決于指針?biāo)赶虻臄?shù)據(jù)類型(T)。
pxn的結(jié)果為:pxnsizeof(T)
二:指針與指針的加運算毫無意義。
三:指針與指針的減運算不同于簡單的數(shù)值之間相減,它用來計算兩指針位置之間的數(shù)據(jù)個數(shù),而不是地址差。px-py的結(jié)果為:(px-py)/sizeof(T)
注意:px和py必須具有相同指針類型!
四:y=px++——y=(px++),注意優(yōu)先級和結(jié)合順序(*和++優(yōu)先級相同且為左結(jié)合)
y=++px——y=(++px)
問題:y=px++和y=(px)++的意義
第13頁/共81頁int*ptr1,*ptr2;
inta[5]={2,4,6,8,10};
intx;
ptr1=&a[0];
ptr2=ptr1+3;
x=ptr2-ptr1;地址ptr1ptr2a數(shù)組108642200020042008200C20102000200C第14頁/共81頁指針的關(guān)系運算一:是對兩個相同類型的指針的運算,如px<py,當(dāng)px所指位置在py之前時,表達(dá)式的值為1,否則為0。二:px==py判斷兩個指針是否指向同一個存儲單元三:px==0,px!=0用來判斷px是否為空指針?biāo)模翰煌愋偷闹羔樢约爸羔樅鸵话阏麛?shù)間的關(guān)系運算是無意義的第15頁/共81頁指針的類型轉(zhuǎn)換
如果兩個指針類型相同,那么可以把一個指針賦給另一個指針,否則必須用強(qiáng)制類型轉(zhuǎn)換運算把賦值運算符右邊指針的類型轉(zhuǎn)換為賦值運算符左邊指針的類型。已知:floata=5.6;
int*ptr_a;
求:如何讓整型指針ptr_a指向浮點型變量a,如何通過指針ptr_a輸出變量a的值?voidmain()
{floata=5.6;
int*ptr_a;
ptr_a=(int*)&a;
cout<<*(float*)ptr_a;
}第16頁/共81頁main()
{inti=3;
char*p1,temp;
p1=(char*)&i;
temp=*p1;
*p1=*(p1+1);
*(p1+1)=temp;
cout<<*(int*)p1;
}例:如何交換一個整型變量在內(nèi)存單元里的高低字節(jié)的內(nèi)容。0000001100000000高字節(jié)低字節(jié)0000000000000011高字節(jié)低字節(jié)輸出結(jié)果:768第17頁/共81頁結(jié)構(gòu)體類型的指針
也可以創(chuàng)建結(jié)構(gòu)體類型的指針變量,其一般格式與創(chuàng)建基本類型的指針變量類似:
《存儲類型》<結(jié)構(gòu)名>*<指針變量>;
結(jié)構(gòu)體類型的指針變量訪問結(jié)構(gòu)體中的成員的方法與一般的結(jié)構(gòu)體變量不同,其一般格式如下:
<指針變量>-><成員>;第18頁/共81頁structperson{ charname[10];
unsignedage;
unsignedlongid;
floatsalary;
};
voidmain()
{ personper1,*per2=&per1;
strcpy(per2->name,"Mary");
per2->age=18;per2->id=20021001;
per2->salary=2250.0;
cout<<per2->name<<'\t'<<per2->age<<'\t‘
<<per2->id<<'\t‘<<per2->salary<<'\n';
}per1.id=20021001//(*per2).salary=2250.0第19頁/共81頁指針與數(shù)組的關(guān)系
聲明了一個數(shù)組TYPEarray[n],則數(shù)組名稱array就有了兩重含義:第一,它代表整個數(shù)組,它的類型是TYPE[n];第二,它是一個指針,該指針的類型是TYPE*,該指針指向的類型是TYPE,也就是數(shù)組單元的類型,該指針指向的內(nèi)存區(qū)就是數(shù)組第0號單元,該指針自己占有單獨的內(nèi)存區(qū),注意它和數(shù)組第0號單元占據(jù)的內(nèi)存區(qū)是不同的。該指針的值是不能修改的,即類似array++的表達(dá)式是錯誤的。
因此數(shù)組與指針有著密切關(guān)系,他們幾乎可以互換,數(shù)組名就是一個常量指針。所以引用指針的概念,要表示數(shù)組元素除了可以用下標(biāo)表示外,還可以用指針位移表示。第20頁/共81頁如:intarray[5]={1,2,3,4,5},*ptr;
ptr=array;
要求:輸出數(shù)組array的各個元素值。下標(biāo)法:
一:for(i=0;i<5;i++)
cout<<array[i];
二:for(i=0;i<5;i++)
cout<<ptr[i];位移法:
一:for(i=0;i<5;i++)
cout<<*(ptr+i);
二:for(i=0;i<5;i++)
cout<<*(array+i);
以上是一維數(shù)組元素的指針表示法,那么二維數(shù)組元素用指針如何表示呢?是否和一維數(shù)組一樣?第21頁/共81頁如:inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
如何用指針表示a[0][1]?
最簡單的方法:int*p=&a[0][0];則*(p+1)即表示a[0][1],很顯然數(shù)組名a是一指針,那是不是*(a+1)就表示a[0][1]呢?
我們知道二維數(shù)組可以看成特殊的一維數(shù)組,這個特殊的一維數(shù)組的元素又是一個一維數(shù)組。即a[3][4]可看成數(shù)組長度為3的一維數(shù)組,而此一維數(shù)組的每個元素又是一個數(shù)組長度為4的一維數(shù)組。如下圖所示:aa[0]a[1]a[2]a[0][0],a[0][1],a[0][2],a[0][3]第22頁/共81頁aa[0]a[1]a[2]a[0][0],a[0][1],a[0][2],a[0][3]
因此,數(shù)組名a代表這個特殊的一維數(shù)組的首地址,它指向第一個元素a[0],則a+1就指向a[1],即二維數(shù)組的第二行元素,這行元素占4個存儲單元。我們稱a為行指針,同理a+1、a+2也是行指針。顯然*(a+1)不表示a[0][1]。
那么如何讓指針真正指到每行上的列元素呢?即我們真正關(guān)心的二維數(shù)組的每一個元素。第23頁/共81頁aa[0]a[1]a[2]a[0][0],a[0][1],a[0][2],a[0][3]
注意:a[0]對二維數(shù)組a來說是元素名,但對一維數(shù)組{a[0][0],a[0][1],a[0][2],a[0][3]}來說卻是數(shù)組名,此為它的雙重身份。很顯然a[0]就指向a[0][0],因此a[0]+1才指向a[0][1],我們稱a[0]為列指針,同理a[1]、a[2]也是列指針。因此*(a[0]+1)就表示a[0][1]。
而a[0]用指針a可表示為*(a+0)即*a,a[1]表示為*(a+1)。第24頁/共81頁aa[0]a[1]a[2]a[0][0],a[0][1],a[0][2],a[0][3]問題一般化:&a[i][j]=a[i]+j=*(a+i)+j
相對應(yīng)的元素是:a[i][j]=*(a[i]+j)=*(*(a+i)+j)
這就是二維數(shù)組元素的指針表示法。參考教材P149可以認(rèn)為:在行指針前加*,可將行指針轉(zhuǎn)換成列指針。第25頁/共81頁下面我們討論行指針、列指針的定義方法。
已知:inta[3][4];
怎樣定義列指針?輸出a[i][j]?
很簡單,只要注意把a(bǔ)的列指針表示方法賦給新的指針即可。如:int*p;
p=&a[0][0];或p=a[0];或p=*a;
cout<<*(p+4*i+j);
如何定義行指針呢?
問題稍微復(fù)雜,新的指針必須指向行,它由4個列元素組成,也就說這個指針應(yīng)指向一個一維數(shù)組,如下定義:int(*p)[4];//見教材P155
p=a;或p=&a[0];
cout<<*(*(p+i)+j);
可以認(rèn)為:在列指針前加&,可將列指針轉(zhuǎn)換成行指針。第26頁/共81頁指針與字符串的關(guān)系
字符串在內(nèi)存以字符數(shù)組存放,自然與指針相關(guān)聯(lián)。定義一:chars[]=“ABC”;定義二:char*s=“ABC”;
s稱之為字符指針變量,它指向字符串“ABC”,即s代表字符串“ABC”的首地址,亦即字符‘A’所在內(nèi)存單元的地址。第27頁/共81頁
我們知道,字符串是不能直接賦值給字符數(shù)組的,要使用函數(shù)strcpy,但字符串可直接賦值給字符指針。
因此:char*s=“ABC”
;可等價為:
char*s;s=“ABC”
;
注意:s為指針,它的值只能為地址,語句s=“ABC”是表示把字符串“ABC”所在內(nèi)存單元的地址賦給S,因此不可認(rèn)為s的值為字符串“ABC”。
用指針表示的字符串輸出同樣可使用
cout<<指針變量名;
上例即cout<<s;第28頁/共81頁
例用指針實現(xiàn)字符串的拷貝(教材P150)voidmain(void){chars1[]="Iamastudent!"; //定義數(shù)組并初始化
char*s2="Youareastudent!";//定義指針并初始化
chars3[30],s4[30],s5[30];inti;char*p1=s3,*p2=s1; //定義指針并初始化
for(;*p1++=*p2++;); //s1拷貝給s3for(i=0;i<=strlen(s1);i++) s4[i]=s1[i]; //s1拷貝給s4strcpy(s5,s2); //s2拷貝給s5}第29頁/共81頁指針數(shù)組
我們先看一個指針定義
char*s[4];
由于[]
比*的優(yōu)先級高(請參考P18),因此以上定義首先定義了一個數(shù)組長度為4的一維數(shù)組,而數(shù)組元素為字符指針。我們稱之為指針數(shù)組。
(注意區(qū)分char(*s)[4]與指針數(shù)組對照,我們稱它為數(shù)組指針)第30頁/共81頁
我們可以初始化這個字符指針數(shù)組,如:
char*s[4]={“open”,”new”,”save”,”saveas”};newsavesaveasopenS[0]S[1]S[2]S[3]
該指針數(shù)組元素指向不同的字符串,注意不要誤認(rèn)為字符串存放在該指針數(shù)組。顧名思義,指針數(shù)組只存放指針,因此該指針數(shù)組存儲的實際上是各字符串的首地址。第31頁/共81頁
大家還注意到各字符串的長度可以不一樣,這是字符指針數(shù)組的一大特點,和二維數(shù)組相比(思考如何用二維數(shù)組存放這幾個字符串?),它大大節(jié)省了內(nèi)存存儲空間。(為什么?)
二維數(shù)組表示如下:
chars[4][8]={“open”,”new”,”save”,”saveas”};S[0]S[1]S[2]S[3]\0saevas\0\0\0\0evas\0\0\0\0\0wen\0\0\0\0nepo第32頁/共81頁例將若干個字符串按升序排序后輸出(教材P152)voidmain(void){char*str[]={…}; //定義數(shù)組并初始化
char*p1; //定義指針
inti,j,k;//按升序排序(改進(jìn)后的選擇排序)for(i=0;i<=4;i++){ k=i; for(j=i+1;j<5;j++) if(strcmp(str[k],str[j])>0)k=j; //k記為當(dāng)前最小字符串的位置
if(k!=i) {p1=str[k];str[k]=str[i];str[i]=p1;}//交換指針的指向,str[i]和str[k]均為指針
}}第33頁/共81頁指針與函數(shù)
指針可以用作函數(shù)參數(shù),這在想通過調(diào)用函數(shù)來改變參數(shù)的值很重要。voidswap(int,int);
voidmain()
{intx1=100,x2=200;
cout<<“交換前x1=“<<x1<<“,x2=”<<x2<<endl;
swap(x1,x2);
cout<<“交換后x1=“<<x1<<“,x2=”<<x2;
}
voidswap(inta,intb)
{inttemp;
temp=a;a=b;b=temp;}100200x1x2x1=100,x2=200進(jìn)入swap函數(shù)
x1,x2分別將值賦給a,btempab100200100200100temp=a;a=b;b=temp;a,b的交換不影響x1,x2退出swap,x1、x2未交換第34頁/共81頁voidswap(int*,int*);
voidmain()
{intx1=100,x2=200;
cout<<“交換前x1=“<<x1<<“,x2=”<<x2<<endl;
swap(&x1,&x2);
cout<<“交換后x1=“<<x1<<“,x2=”<<x2;
}
voidswap(int*p1,int*p2)
{inttemp;
temp=*p1;
*p1=*p2;
*p2=temp;
}100200x1x2x1=100,x2=200進(jìn)入swap函數(shù),分別將x1、x2的地址賦給p1,p2p1p2temp&x1&x2100200100temp=*p1;*p1=*p2;*p2=temp;swap函數(shù)執(zhí)行過程中p1,p2的值沒有變化,退出swap函數(shù)后,x1,x2的值交換。第35頁/共81頁
實際上,傳址方式是一種特殊的傳值方式。將指針變量的值傳遞給形參(當(dāng)然形參也應(yīng)該是指針變量),由于指針變量的值就是地址,所以這種傳值方式就成為了傳址方式。特別要注意,傳值方式中形參的改變不會影響到實參的改變,這一點傳址方式也不例外!上例中之所以能交換實參所指向的兩個數(shù),是因為在函數(shù)中交換的是形參所指向的變量的值,由于形參和實參指向同一個變量,因此實參指向變量最終交換,但實參的值卻沒有變化。第36頁/共81頁voidswap(int*,int*);
voidmain()
{intx1=100,x2=200,*pt1=&x1,*pt2=&x2;
cout<<“交換前x1=“<<x1<<“,x2=”<<x2<<endl;
swap(pt1,pt2);
cout<<“交換后x1=“<<x1<<“,x2=”<<x2;
}
voidswap(int*p1,int*p2)
{int*temp;
temp=p1;
p1=p2;
p2=temp;
}第37頁/共81頁intmax,min;
voidmax_min_value(int*p,intn)
{inti;
max=min=*p;
for(i=1,p++;i<n;i++,p++)
if(*p>max)max=*p;
elseif(*p<min)min=*p;
}
voidmain()
{intnumber[10],i;
for(i=0;i<10;i++)
cin>>number+i;
max_min_value(number,10);
cout<<“max=“<<max<<“min=”<<min;}例:從10個數(shù)中找出其中的最大值和最小值。第38頁/共81頁例:有一個班,3個學(xué)生各4門成績,要求查找有成績不及格的學(xué)生,并輸出該學(xué)生的全部成績。voidsearch(float*p,intm,intn)
{inti,j,flag;
for(i=0;i<m;i++)
{flag=0;
for(j=0;j<n;j++)
if(*(p+i*n+j)<60){flag=1;break;}
if(flag==1){printf(“\nNO.%dfails,hisscore:\n”,i);
for(j=0;j<n;j++)
printf(“%8.1f”,*(p+i*n+j));
}
}
}
main()
{floatscore[3][4]={......};
.......search(score[0],3,4);......}voidsearch(float(*p)[4],intm)
{inti,j,flag;
for(i=0;i<m;i++)
{flag=0;
for(j=0;j<4;j++)
if(*(*(p+i)+j)<60){flag=1;break;}
if(flag==1)
{cout<<“\nNO.”<<i<<“fails,hisscore:\n”;
for(j=0;j<4;j++)
cout<<*(*(p+i)+j);
}
}
}
main()
{floatscore[3][4]={......};
.......search(score,3);......}第39頁/共81頁例:制作一個簡單的菜單。voidmenu(char*p[],intm)
{inti;
system(“cls”);
for(i=0;i<m;i++)
{cout<<p[i];
}
cout<<“\nEnterachoice:”;
}
main()
{char*p[4]={“Open”,”New”,”Save”,”Saveas”};
menu(p,4);
}第40頁/共81頁返回指針的函數(shù)voidstrcpy(char
s1[],chars2[])
{inti=0;
while(s2[i]!=‘\0’)
{s1[i]=s2[i];
i++;
}
s1[i]=‘\0’;
}char*strcpy(char
*s1,char*s2)
{inti=0;while(*(s2+i)!=‘\0’)
{*(s1+i)=*(s2+i);
i++;
}
s1[i]=‘\0’;
returns1;
}第41頁/共81頁注意:返回指針的函數(shù),其函數(shù)體中的return語
句的參數(shù)必須為全局變量的指針、靜態(tài)變量指針
或形參的指針(如果形參為指針類型或引用類型
的話),不能為局部變量指針。返回的是變量地址,必須保證函數(shù)返回后,這個變量仍然存在。要返回函數(shù)中局部變量的地址,應(yīng)聲明為靜態(tài)的。char*string_name(intn){staticchar*string[]={“illegalstring”,“string1”,“string2”,“string3”}return(n<1||n>3)?string[0]:string[n];}第42頁/共81頁例將輸入的一個字符串按逆序輸出(教材P164)char*flip(char*ptr) //指針函數(shù){char*p1,*p2,temp; p1=p2=ptr; //初始化指針變量,p1、p2指向字符串的起始
while(*p2++);//p2指向字符串結(jié)束符的后一個位置
p2=p2-2; //p2回退兩個位置,指向字符串的最后一個字符
while(p1<p2){ //指針的比較和內(nèi)容的交換
temp=*p2; *p2--=*p1; //從字符串的兩邊向中間進(jìn)行交換 *p1++=temp; }returnptr; //返回指針}第43頁/共81頁例設(shè)計字符拷貝和拼接的函數(shù)(教材P165)char*copy(char*to,char*from) //字符拷貝指針函數(shù){
char*p=to;
while(*to++=*from++)
; //內(nèi)容拷貝
returnp; //返回指針}char*stringcat(char*to,char*from)//字符拼接指針函數(shù){
char*p=to;
while(*to++)
;
//指針指向結(jié)束字符后一個字符
to--; //指針減1,指向結(jié)束字符
while(*to++=*from++)
; //內(nèi)容拼接
returnp; //返回指針}第44頁/共81頁指向函數(shù)的指針
函數(shù)名實際上是完成函數(shù)任務(wù)的代碼所在內(nèi)存中的起始地址(函數(shù)入口地址),亦即函數(shù)名象數(shù)組名一樣,本身就是一個指針,因此函數(shù)名也可作為函數(shù)的參數(shù)。
函數(shù)名作為實參很簡單,直接使用函數(shù)名即可,但由于函數(shù)名本身就是一個指針,所以它作為形參時必須使用指針定義。
如:intmax(int,int);
則指向函數(shù)max的指針可定義為:
int(*max_ptr)(int,int);
注意與int*max_ptr(int,int)
區(qū)分,它是一個返回指針的函數(shù)。第45頁/共81頁
函數(shù)指針常用在所謂較簡單的菜單驅(qū)動系統(tǒng)中,每一個菜單選項對應(yīng)一個功能即一個函數(shù),由于菜單不只一項,所以要用到指向函數(shù)的指針數(shù)組。如:
int(*function[3])(int,int);
使用指向函數(shù)的指針數(shù)組的一個限制是所有的指針都必須是同一個類型,指針指向的函數(shù)必須具有相同類型的返回值,并且它們的參數(shù)類型也相同。
對于上例如果有:intmax(int,int);
intmin(int,int);
intaverage(int,int);
則上例的指針數(shù)組可初始化為:
int(*function[3])(int,int)={max,min,average};
第46頁/共81頁二級指針voidmain()
{char*p1=“Nanjing”;
char**p2;
p2=&p1;
cout<<*p2<<endl;
}voidmain()
{inta[4]={1,2,3,4};
int(*p)[4],i;
p=&a;
for(i=0;i<4;i++)
cout<<(*p)[i]<<endl;
}第47頁/共81頁總結(jié):如何判斷指針類型?
要弄懂指針就要弄懂3個問題:指針的類型、指針?biāo)赶虻念愋?、指針的值。int*p;int*int
float*p;float*float
int**p;int**int*
int(*p)[3]int(*)[3]int()[3]int[3]
int*p[3]指針數(shù)組
int(*p)()int(*)()int()
int*p()返回指針的函數(shù)第48頁/共81頁動態(tài)分配內(nèi)存空間new運算符可以為所創(chuàng)建的指針變量動態(tài)地分配存儲空間,而運算符delete則用于釋放動態(tài)分配的存儲空間。第49頁/共81頁
使用new運算符的一般格式為:
<指針變量>=new<類型>《(初始值)》;
或
<指針變量>=new<類型>[<表達(dá)式>];
第一種形式為<指針變量>所指向的數(shù)據(jù)分配大小為sizeof(<類型>)個字節(jié)的連續(xù)存儲空間,初始值表示為所分配的存儲空間指定初始值。第二種形式為<指針變量>所指向的數(shù)據(jù)分配指定大小的數(shù)組空間,<表達(dá)式>為整型變量或常量。第50頁/共81頁
對于上述兩種情形,如果動態(tài)分配不成功,則new運算符返回NULL(0);如果成功分配,則new運算符返回所分配的存儲空間的首地址,并將該地址賦給<指針變量>。使用delete的一般格式為:
delete <指針變量>;
或
delete[《<表達(dá)式>》]<指針變量>;
第一種格式為將動態(tài)分配給<指針變量>的內(nèi)存空間歸還給系統(tǒng),第二種格式為將動態(tài)分配給<指針變量>的數(shù)組空間歸還給系統(tǒng)。第51頁/共81頁#include<iostream.h>voidmain(){int*p1,*p2;float*p3;
p1=newint;*p1=2;cout<<*p1<<'\n';
p2=newint(4);*p2=6;cout<<*p2<<'\n';
p3=newfloat(5.2);cout<<*p3<<'\n';
deletep1;
deletep2;
deletep3;p1=newint(6);cout<<*p1<<'\n';deletep1;}一般動態(tài)分配第52頁/共81頁#include<iostream.h>#include<string.h>voidmain(){int*p4,n;char*p5;n=4;p4=newint[n];
//動態(tài)分配一維數(shù)組
for(inti=0;i<n;i++)p4[i]=2*i;for(i=0;i<n;i++)cout<<p4[i]<<'\t';
p5=newchar[10];strcpy(p5,"abcdefg"); cout<<p5<<'\n';delete[]p4;delete[]p5;}一維數(shù)組動態(tài)分配第53頁/共81頁#include<iostream.h>#include<string.h>voidmain(){int(*p6)[4];
p6=newint[2][4];for(inti=0;i<2;i++){for(intj=0;j<4;j++){p6[i][j]=i+j;cout<<p6[i][j]<<'\t';}cout<<'\n';}
delete[2]p6;}二維數(shù)組動態(tài)分配第54頁/共81頁
注意,在用new運算符為某個指針變量所指向的數(shù)據(jù)動態(tài)分配存儲空間之后,必須用delete運算符撤消,否則該存儲空間將一直被占用,直到關(guān)閉電腦。
用new和delete還可以為結(jié)構(gòu)類型或其它用戶自定義類型的指針動態(tài)分配內(nèi)存空間。第55頁/共81頁structnode
{ intx;
floaty;
charz[10];
};voidmain()
{ node*pn;
pn=newnode;
pn->x=2;
pn->y=4.3;
strcpy(pn->z,"China!");
cout<<pn->x<<'\t'<<pn->y<<'\t'<<pn->z<<'\n';
deletepn;
}第56頁/共81頁
在使用new和delete運算符時,要注意如下幾點:
(1)如果new運算符動態(tài)分配內(nèi)存失?。▋?nèi)存中沒有符合要求的空閑的連續(xù)內(nèi)存單元),則返回NULL(0),此時指針為空指針。此時,要進(jìn)行空指針判斷處理。float*fp;
fp=newfloat[5000];
if(fp==0)
{cout<<“動態(tài)分配內(nèi)存失敗,程序終止運行!\n”;
exit(3);
}第57頁/共81頁(2)動態(tài)分配存放數(shù)組的內(nèi)存空間時,不能在分配空間的同時進(jìn)行初始化。如:int*pi=newint[8]{1,2,3,4,5,6,7,8};r第58頁/共81頁(3)可以用new運算符動態(tài)分配多維數(shù)組空間,但要注意的是,它返回的是行指針。當(dāng)撤消動態(tài)分配二維數(shù)組空間時,一定要指明數(shù)組的行數(shù),否則只能撤消第0行的內(nèi)存空間。float*pf1;
pf1=newfloat[3][5];
//錯誤!類型不匹配。
float(*pf)[5];
pf=newfloat[3][5];
delete[3]pf;
//注意pf前的行數(shù)不可省略!第59頁/共81頁(4)動態(tài)分配的二維數(shù)組的列向量要與指向數(shù)組的指針變量中的數(shù)組大小一致,而行向量可為任意的正整數(shù)。如:float(*pf)[5];pf=newfloat[3][6];
//錯誤!類型不匹配。第60頁/共81頁引用
引用是另一個變量別名,或另一個變量的同義詞,引用變量依附于另一個變量而定義。定義引用類型變量的一般格式為:
<類型>&<變量名1>=<變量名2>;
其中<變量名1>為引用類型的變量,而<變量名2>必須是已經(jīng)定義過的且與引變量同類型的變量。
intI=0;int&j=I;第61頁/共81頁
在定義一個引用變量時,編譯系統(tǒng)并不會為其單獨分配存儲空間,因此必須對它進(jìn)行初始化,將它與某個已定義的同類型的變量相關(guān)聯(lián)。在定義一個引用變量之后,它與所引用的變量共享同一個內(nèi)存空間,并隨著所引用的變量的撤銷而撤銷,因此對引用的任何操作都是對它所關(guān)聯(lián)的變量的操作。第62頁/共81頁voidmain()
{ intk,&ref=k;
k=100;
cout<<"&k:"<<&k<<"\t&ref:"<<&ref<<'\n';
cout<<"k="<<k<<"\tref="<<ref<<'\n';
ref+=200;
cout<<"k="<<k<<"\tref="<<ref<<'\n';
intl=500;
ref=l;
cout<<"k="<<k<<"\tref="<<ref<<"\tl="<<l<<'\n';
cout<<"&k:"<<&k<<"\t&ref:"<<&ref<<"\t&l:"<<&l<<'\n';
}0x20000x20001001003003005005005000x20000x20000x1FF8第63頁/共81頁voidfun()
{ inti=10;
staticint&j=i;
j++;
cout<<j<<'\n';
}voidmain()
{fun();
fun();
}1111第64頁/共81頁
對于引用類型的變量時,要注意如下幾個問題:
1.在定義引用類型的變量時,必須用同類型的已定義的變量對它初始化,不同類型的變量以及常量不可對它初始化!如:int&ref1;//錯誤,未初始化intI;float&ref2=I;//錯誤,類型不一致int&ref3=4;//錯誤,不可用常量初始化第65頁/共81頁2.可以將引用與指針變量所指向的數(shù)據(jù)相關(guān)聯(lián),也可以將引用與數(shù)組中的元素相關(guān)聯(lián)。如:
Int*pi=newint(3);
int&ref1=*pi;
inta[10];
int&ref2=a[3];
3.可以定義指針類型的引用。
int*pi=newint;
int*&ref1=pi;
inta[10];
int*&ref2=a;第66頁/共81頁4.可以定義對引用類型變量的引用,但不能定義引用的引用,也不能定義引用指針和引用數(shù)組。如:
intI,&ref1=i;
int&ref2=ref1;
int&&ref3=i;
//錯誤,不能定義引用的引用
inta[8];
int&*ref4=a;
//錯誤,不能定義引用指針
int&ref5[8]=a;
//錯誤,不能定義引用數(shù)組第67頁/共81頁引用和函數(shù)
參數(shù)的三種傳遞方式:值傳遞、地址傳遞、引用傳遞。
當(dāng)函數(shù)的形參為引用類型時,調(diào)用該函數(shù)的方式稱為引用傳遞。第68頁/共81頁
引用傳遞具有某些與地址傳遞相似的特征,即引用類型的參數(shù)既可以作為輸入?yún)?shù),也可以作為輸出參數(shù)。對引用類型的參數(shù)的操作實際上就是對傳遞給它的實參的操作,而不需要將實參拷貝一個副本給形參,這是與其它兩種傳遞
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年河北唐山南堡汽車客運站招聘筆試參考題庫附帶答案詳解
- Unit 1 Making friends Part A Lets talk(教學(xué)設(shè)計)-2024-2025學(xué)年人教PEP版(2024)英語三年級上冊
- 03 11 短文二篇2024-2025學(xué)年八年級語文上冊同步教學(xué)設(shè)計(河北專版)
- 第14課 明至清中葉的經(jīng)濟(jì)與文化教學(xué)設(shè)計-2023-2024學(xué)年高中歷史統(tǒng)編版(2019)必修中外歷史綱要上冊
- 10-2《師說》教學(xué)設(shè)計 2024-2025學(xué)年統(tǒng)編版高中語文必修上冊
- 2024四川九洲投資控股集團(tuán)有限公司招聘黨建干事崗2人筆試參考題庫附帶答案詳解
- Module8 Unit1 While the traffic lights were changing to red,a car suddenly appeared.教學(xué)設(shè)計2024-2025學(xué)年外研版英語八年級上冊
- 粵教版信息技術(shù) 必修 3.3.1 制作多媒體作品的基本過程教學(xué)設(shè)計
- 14-1《故都的秋》教學(xué)設(shè)計 2024-2025學(xué)年統(tǒng)編版高中語文必修上冊
- 2025年河南科技職業(yè)大學(xué)單招職業(yè)技能測試題庫完整
- 2025年度個人住房買賣合同(帶家居家具)
- 生產(chǎn)車間布局優(yōu)化與現(xiàn)場改善的策略研究
- 三方公司合作協(xié)議書范本
- 護(hù)理責(zé)任組長續(xù)聘競聘
- 2024-2025學(xué)年第二學(xué)期教學(xué)教研工作安排表
- 2025年貴州云上產(chǎn)業(yè)服務(wù)有限公司招聘筆試參考題庫含答案解析
- 2025年南京信息職業(yè)技術(shù)學(xué)院高職單招職業(yè)適應(yīng)性測試近5年??及鎱⒖碱}庫含答案解析
- 2025-2030年中國天然氣行業(yè)發(fā)展分析及發(fā)展趨勢預(yù)測報告
- 《雷達(dá)信號處理基礎(chǔ)》課件
- 2025屆貴州省興義市三年級數(shù)學(xué)第一學(xué)期期末達(dá)標(biāo)檢測試題含解析
- 人教版地理七年級下冊7.1.2 亞洲的自然環(huán)境(課件39張)
評論
0/150
提交評論