C指針和引用實用_第1頁
C指針和引用實用_第2頁
C指針和引用實用_第3頁
C指針和引用實用_第4頁
C指針和引用實用_第5頁
已閱讀5頁,還剩76頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論