版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
第五章數(shù)組與指針本章將深入學(xué)習(xí)數(shù)組包括多維數(shù)組的知識和應(yīng)用,揭示數(shù)組與指針的關(guān)系。
C(C++)語言擁有獲得變量地址和操縱地址的能力,用來操縱地址的變量稱為指針。5.1
數(shù)組復(fù)習(xí):1、數(shù)據(jù)組織方式、定義方式、存儲方式、元素訪問方式2、使用方法inta[100];charstr[40];Studentslist[50];Complexc_array[100];//結(jié)構(gòu)體數(shù)組//對象數(shù)組(1)對下標(biāo)變量做循環(huán)操作:(2)以數(shù)組做為函數(shù)參數(shù):for(i=0;i<n;i++)
cin>>a[i];Input(a,100);3、舉例:voidInput(inta[],intn);數(shù)組變量定義:例:定義數(shù)組
inta[10];doublea1[100];inta2[16],n,a3[23],m;voidf(intn,intm){
int
b[n];…}//ok//ok//錯,b的大小依賴于形參,在編譯時無法確定,因為編譯時無法確定數(shù)組
//大小,所以必須明確告訴數(shù)組大小數(shù)組的初始化:*定義時直接初始化例:
inta[4]={1,1,2,4};
intb[4]={1,2};
intc[]={1,2,3,4,5,6,7,8,};注意:這種寫法只能用于數(shù)組初始化時。語句里不允許采用這種寫法。數(shù)組元素可通過普通賦值語句設(shè)置。//b[2],b[3]自動初始化為0數(shù)組的初始化:intarray[5]={1,2,3,4,5,6};//錯intarray[]={1,2,3,4,5,6};//okintarray[5]={1,,3,4,5,6};//錯intarray[5]={1,2,3};//okintarray[]={0};//okintarray[5]={};//錯數(shù)組的存儲實現(xiàn)數(shù)組占據(jù)一連續(xù)存儲區(qū),元素順序排列,0號元素在最前面,各元素占相同空間。如有inta[6];
a[0]a[1]a[2]a[3]a[4]a[5]a數(shù)組名是數(shù)組元素的內(nèi)存地址,數(shù)組名是一個常量,不能被賦值。數(shù)組a200020042008201220162020a[0]a[1]a[2]a[3]a[4]a[5]例:
intfibon[10]={0,1,1,2,3,5,8,13,21,34};
0123
2134fibon[0]fibon[1]fibon[2]fibon[3]fibon[8]fibon[9]數(shù)組在內(nèi)存中的存儲數(shù)組名為fibon,這是一個包含10個整型元素的一維數(shù)組,第一個元素為fibon[0],存放0,最后一個元素為fibon[9],存放34。數(shù)組元素的訪問方式:通過下標(biāo)操作符,按元素在數(shù)組中的位置進行訪問,稱為索引訪問或下標(biāo)訪問。cout<<fibon[8]<<endl;輸出:21編譯程序不檢查下標(biāo)越界錯誤。C++程序員必須保證下標(biāo)不越界。數(shù)組的使用*sizeof(a)數(shù)組a存儲量//40=10*4*sizeof(a[0])數(shù)組a大小//4*sizeof(a)/sizeof(a[0])數(shù)組a的元素個數(shù)//10例:
inta[10]={0,1,1,2,3,5,8,13,21,34};
例:#include<iostream.h>intx[5];//全局變量voidmain(){
inti;for(i=0;i<5;i++)cout<<x[i]<<'\t';
cout<<endl;
inty[5];//局部變量
for(i=0;i<5;i++)cout<<y[i]<<'\t';
cout<<endl; }={1,2,3}輸出:000005個隨機數(shù)輸出:0000012300
constSIZE=15;
intmain(){
int
arr[SIZE],i,high,low;
for(i=0;i<SIZE;i++)arr[i]=rand()%100;//產(chǎn)生100以內(nèi)隨機數(shù)
cout<<"Herearethe"<<SIZE<<"randomnumbers:"<<endl;
for(i=0;i<SIZE;i++)cout<<arr[i]<<'\t';
cout<<endl;high=arr[0];//初始化時最大和最小值均為數(shù)組首元素
low=arr[0];
for(i=1;i<SIZE;i++){if(arr[i]>high)high=arr[i];
if(arr[i]<low)low=arr[i];}
cout<<"highestvalueis"<<high<<endl;
cout<<"lowestvalueis"<<low<<endl;
return0;}【例5.1】找出整型數(shù)組各元素中的最大數(shù)和最小數(shù)。數(shù)組中的數(shù)由隨機數(shù)函數(shù)rand()產(chǎn)生。5.1.2數(shù)組名作為函數(shù)參數(shù)數(shù)組名作為參數(shù):
數(shù)組名可以作為函數(shù)的參數(shù)。在函數(shù)調(diào)用時傳遞實參數(shù)組的首地址,所以在被調(diào)函數(shù)中對形參數(shù)組的處理實際就是對調(diào)用函數(shù)的實參數(shù)組的處理。
C++只傳遞數(shù)組首地址,而對數(shù)組邊界不加檢查。好處:
函數(shù)對長度不等的同類數(shù)組都通用。如要指定長度可以設(shè)定另一個參數(shù)來傳遞數(shù)組元素的個數(shù)?!纠?.2】字符數(shù)組與字符數(shù)組相連接
void
strcat(chars[],charct[]){
inti=0,j=0;
while(s[i]!=0)i++;//指針移到s數(shù)組尾部
while(ct[j]!=0)
s[i++]=ct[j++];//將ct數(shù)組中的元素添加到s數(shù)組尾部
s[i]='\0';}intmain(void){
chara[40]="李明";
charb[20]="是東南大學(xué)學(xué)生";
strcat(a,b);
cout<<a<<endl;//打印字符數(shù)組a
return0;}ABCDEFG\0
HIJK\0void
strcat(char
s[],charct[]){
inti=0,j=0;
while(s[i]!=0)i++;//指針移到s數(shù)組尾部
while(ct[j]!=0)
s[i++]=ct[j++];//將ct數(shù)組中的元素添加到s數(shù)組尾部
s[i]='\0';}
chara[40]=“ABCDEFG";charb[20]=“HIJK";
strcat(a,b);asbctABCDEFG
HIJK\0void
strcat(char
s[],charct[]){
inti=0,j=0;
while(s[i]!=0)i++;//指針移到s數(shù)組尾部
while(ct[j]!=0)
s[i++]=ct[j++];//將ct數(shù)組中的元素添加到s數(shù)組尾部
s[i]='\0';}
chara[40]=“ABCDEFG";charb[20]=“HIJK";
strcat(a,b);asbctHvoid
strcat(char
s[],charct[]){
inti=0,j=0;
while(s[i]!=0)i++;//指針移到s數(shù)組尾部
while(ct[j]!=0)
s[i++]=ct[j++];//將ct數(shù)組中的元素添加到s數(shù)組尾部
s[i]='\0';}
chara[40]=“ABCDEFG";charb[20]=“HIJK";
strcat(a,b);as
HIJK\0bctABCDEFGH
Ivoid
strcat(char
s[],charct[]){
inti=0,j=0;
while(s[i]!=0)i++;//指針移到s數(shù)組尾部
while(ct[j]!=0)
s[i++]=ct[j++];//將ct數(shù)組中的元素添加到s數(shù)組尾部
s[i]='\0';}
chara[40]=“ABCDEFG";charb[20]=“HIJK";
strcat(a,b);as
HIJK\0bctABCDEFGH
IJvoid
strcat(char
s[],charct[]){
inti=0,j=0;
while(s[i]!=0)i++;//指針移到s數(shù)組尾部
while(ct[j]!=0)
s[i++]=ct[j++];//將ct數(shù)組中的元素添加到s數(shù)組尾部
s[i]='\0';}
chara[40]=“ABCDEFG";charb[20]=“HIJK";
strcat(a,b);as
HIJK\0bctABCDEFGH
IJKvoid
strcat(char
s[],charct[]){
inti=0,j=0;
while(s[i]!=0)i++;//指針移到s數(shù)組尾部
while(ct[j]!=0)
s[i++]=ct[j++];//將ct數(shù)組中的元素添加到s數(shù)組尾部
s[i]='\0';}
chara[40]=“ABCDEFG";charb[20]=“HIJK";
strcat(a,b);as
HIJK\0bctABCDEFGH
IJK\0例:用數(shù)組名作函數(shù)參數(shù)實現(xiàn)逆序輸出constintn=4;voidinvert(inta[]){
inti,temp;for(i=0;i<n/2;i++){
temp=a[i];
a[i]=a[n-1-i];
a[n-1-i]=temp;
}}intmain(){
int
i,b[n];for(i=0;i<n;i++)cin>>b[i];invert(b);for(i=0;i<n;i++)cout<<b[i]<<'\t';
cout<<endl;return0;}b1,2,3,4ba1,2,3,4invert(b)執(zhí)行之初ba4,3,2,1invert(b)執(zhí)行到末尾b4,3,2,1invert(b)執(zhí)行之后5.2多維數(shù)組
[6]計算機對“二維數(shù)組”的解釋處理該表的數(shù)組定義為:119753117131175312108642mat[0]mat[1]mat[2]——數(shù)組的數(shù)組mat[3]int按行存儲(二維拉成一維)——元素地址的計算(1)對下標(biāo)變量做循環(huán)操作:(2)以數(shù)組做為函數(shù)參數(shù):二維數(shù)組的初始化:
intmat[3][6]={1,1,2,4};
intmat[3][6]={{1,1,2,4},{3,6,2}};
intmat[][6]={{1,1,2,4},{3,6,2}};使用方法for(i=0;i<n;i++)
for(j=0;j<m;j++)
cin>>a[i][j];形參數(shù)組可省略第一維
例:
floata[3][4];把二維數(shù)組看作是一種特殊的一維數(shù)組:它的元素又是一個一維數(shù)組。如:把a數(shù)組看成一維數(shù)組:
a[0]-----------a[0][0]a[0][1]a[0][2]a[0][3]
a
a[1]-----------a[1][0]a[1][1]a[1][2]a[1][3]
a[2]-----------a[2][0]a[2][1]a[2][2]a[2][3]二維數(shù)組的引用二維數(shù)組的元素的表示形式為:
數(shù)組名
[下標(biāo)][下標(biāo)]如
a[2][3]
下標(biāo)可以是整型表達(dá)式,如
a[2-1][2*2-1]。數(shù)組元素是左值,可以出現(xiàn)在表達(dá)式中,也可以被賦值。例
b[1][2]=a[2][3]/2;二維數(shù)組的初始化*定義時直接初始化inta[3][2]={{1,2},{3,4},{5,6}};inta[3][2]={1,2,3,4,5,6};inta[][2]={{1,2},{3,4},{5,6}};inta[][2]={1,2,3,4,5,6};兩種寫法效果一樣兩種寫法效果一樣第一維(高維)可省,低維不可省可以對部分元素賦初值
inta[3][4]={{1},{5},{9}};只對各行第1列的元素賦初值,其余元素值自動置為0。
100050009000也可以對各行中的某一元素賦初值:
inta[3][4]={{1},{0,6},{0,0,11}};初始化后的數(shù)組元素如下:
1000060000110也可以只對某幾行元素賦初值:
inta[3][4]={{1},{5,6}};數(shù)組元素為:
100056000000
第3行不賦初值。二維數(shù)組的使用和表示設(shè):doublea[3][2];
a代表數(shù)組整體,a[0]、a[1]和a[2]是成員數(shù)組,一維數(shù)組,a[0][1]表示a的0元素數(shù)組中下標(biāo)1的元素,可作為整型變量。例:
a[2][1]=a[0][1]+a[1][1];
for(i=0;i<3;i++)
for(j=0;j<2;j++)a[i][j]=i+j;二維數(shù)組的存儲*數(shù)組元素連續(xù)存儲,例:doublea[3][2];
a的開始位置也是其首成員a[0]的開始位置,也是a[0]首成員a[0][0]的位置。有了確定的關(guān)系后可以算出多維數(shù)組任一元素在內(nèi)存的位置,設(shè)有a數(shù)組m行n列,每個元素占b個字節(jié),a[i][j]的首地址為:
數(shù)組的首地址+(i*n+j)*b;注意:
復(fù)合類型只能對各元素逐個操作,不能整體操作。
圖5.36*3*4的三維數(shù)組多維數(shù)組分析:
C/C++對數(shù)組的理解可推廣至所謂的“多維數(shù)組”??啥x為:int
d[6][3][4];例:輸出30個學(xué)生8門功課的成績#include<iostream.h>voidmain(){
intgrades[30][8];
inti,j;for(i=0;i<30;i++)for(j=0;j<8;j++)
cin>>grades[i][j];for(i=0;i<30;i++){
cout<<i+1<<"號學(xué)生的成績:"<<endl;for(j=0;j<8;j++)cout<<grades[i][j]<<"
";
cout<<endl;}}//鍵入1號同學(xué)8門功課的成績….若,二重循環(huán)改寫成如下形式:for(j=0;j<8;j++)for(i=0;i<30;i++)
cin>>grades[i][j];//鍵入1號到30號同學(xué)的第1門功課的成績….例:用數(shù)組元素作函數(shù)的實參#include<iostream.h>voidmain(){
int
max_value(int
x,intmax);//函數(shù)聲明
inti,j,row=0,colum=0,max;
inta[3][4]={{5,12,23,56},{19,28,37,46},{-12,-34,6,8}};max=a[0][0];for(i=0;i<=2;i++)for(j=0;j<=3;j++){max=max_value(a[i][j],max);
if(max==a[i][j]){row=i;colum=j;}}//i行號,j列號
cout<<"max="<<max<<",row="<<row<<",colum="<<colum<<endl;}輸出:
max=56,row=0,colum=3int
max_value(int
x,intmax){if(x>max)returnx;elsereturnmax;}1416192589101571212182024741361091013141567511109878129412231516691153152619221445321821171693211191713117530076543210圖5.4極點與鞍點示意圖【例5.4】已知矩陣
intmat[8][8],找出其中的極點與鞍點。如某元素在所在行相鄰點中與所在列相鄰點中均為最大或最小,則為極點;如某元素在所在行(或列)相鄰點中為最大,同時該元素在所在列(或行)相鄰點中為最小,則為鞍點。mat[2][4]→極大點mat[2][6]→極大點mat[4][1]→極大點mat[5][2]→極大點mat[6][3]→極大點mat[2][5]→鞍點mat[3][3]→極小點mat[5][6]→極小點mat[6][1]→極小點#include<iostream>singnamespacestd;intmat[8][8]={0,3,5,7,11,┅,25,19,16,14};
int
maxmin(int
a,int
b,intc){
if(a>b&&b<c)//判斷相鄰3元素中間元素是否最大或最小
return-1;//b為最小返回-1
else
if(a<b&&b>c)return1;//b為最大返回1
else
return0;//其它返回0}b:為最大返回1,最小返回-1,其它返回0intmain(){
int
i,j,k,l;
for(i=1;i<=6;i++)//第1行第1列,最后1行,最后1列不在比較之列
for(j=1;j<=6;j++){
k=maxmin(mat[i][j-1],mat[i][j],mat[i][j+1]);
//行元素比較
if(k==0)continue;l=maxmin(mat[i-1][j],mat[i][j],mat[i+1][j]);//列元素比較
if(l==0)continue;
if(k==1&&l==1)cout<<"極大點:";elseif(k==-1&&l==-1)cout<<"極小點:";elsecout<<“鞍點:”;
cout<<mat[i][j]<<"i="<<i<<";j="<<j<<endl;}return0;}【例5.5】矩陣轉(zhuǎn)置與矩陣相乘。下標(biāo)作為參數(shù)傳遞。voidinverse(int[3][6],int[6][3]);//轉(zhuǎn)置矩陣voidmulti(int[6][3],int[3][4],int[6][4]);//矩陣乘法voidoutput(int[6][4]);//矩陣輸出intmain(){
intmiddle[6][3],result[6][4];
intmatrix1[3][6]={8,10,12,23,1,3,5,7,9,2,4,6, 34,45,56,2,4,6};
intmatrix2[3][4]={3,2,1,0,-1,-2,9,8,7,6,5,4};inverse(matrix1,middle);multi(middle,matrix2,result);
output(result);return0;}void
inverse(intmatrix1[3][6],intmiddle[6][3]){//轉(zhuǎn)置矩陣
int
i,j;
for(i=0;i<3;i++)
for(j=0;j<6;j++)middle[j][i]=matrix1[i][j];}810122313853457924610745344556246129562322144366matrix1[3][6]middle[6][3]voidmulti(intmiddle[6][3],intmatrix2[3][4],intresult[6][4]){
inti,j,k;
//矩陣乘法
for(i=0;i<6;i++){
for(j=0;j<4;j++){
result[i][j]=0;
for(k=0;k<3;k++)
result[i][j]+=middle[i][k]*matrix2[k][j];}}}8534107451295623221443663210-1-2987654*25721022317627629823634237329654512418574845308772middle[6][3]matrix2[3][4]result[6][4]void
output(intresult[6][4]){//矩陣輸出
cout<<"result"<<'\n';
int
I,j;
for(i=0;i<6;i++){
for(j=0;j<4;j++)
cout<<setw(4)<<result[i][j]<<"";
cout<<'\n';}}5.3
指針與地址
5.3.1指針的概念5.3.2指針變量的賦值、初始化與簡單應(yīng)用指針是C++語言中的重要概念,也是C++語言的重要特色。使用指針,可以使程序更加簡潔、緊湊、高效。指針(Pointer)是什么?為什么要使用指針?(1)指針──即地址指針就是一個地址,它指向了內(nèi)存中的一個數(shù)據(jù)單元。在win32中,指針是一個32位無符號整數(shù)。(4字節(jié))指針就像門牌號碼,門牌號碼的長度都一樣,但是對應(yīng)的房子的大小各不相同。5.3.1指針的概念1.內(nèi)存地址──內(nèi)存中存儲單元的編號變量地址──系統(tǒng)分配給變量的內(nèi)存單元的起始地址3.變量值的存取──通過變量在內(nèi)存中的地址進行
(1)直接訪問──直接利用變量的地址進行存取(通過變量名或地址訪問一個變量的方式)(2)間接訪問──通過另一變量訪問該變量的值(3)為表示指針變量和它指向的變量之間的關(guān)系,用指針運算符“*
”表示。指針除了可以指向變量之外,還可以指向內(nèi)存中其他任何數(shù)據(jù)結(jié)構(gòu),如數(shù)組,結(jié)構(gòu)體和聯(lián)合體等,它還可以指向函數(shù)。(2)指針變量──專門用于存儲其它變量地址的變量。
例:inta=6;
int*p=&a;
指針變量p的值就是變量a的地址。指針與指針變量的區(qū)別,就是變量值與變量的區(qū)別。2000pa20006間接訪問指針類型變量的定義格式:
存儲類型*變量名;如:int*p1;double*ptitle;char*ptr;指針類型指:它所指向變量的類型,而不是指針本身數(shù)據(jù)值的類型,任何一個指針本身的數(shù)據(jù)值都是unsignedlongint型(4字節(jié))。p1,ptitle和ptr的長度相等指針的聲明:5.3.2指針變量的賦值、初始化與簡單應(yīng)用指針是一個變量,在程序中使用時,必須先聲明,后使用。在指針聲明的同時也可以進行初始化。
指針的定義:
存儲類型數(shù)據(jù)類型*指針變量名;例:int*p1; staticint*p2; char*da;inta;int*pa=&a;合法定義&:
表示取地址*:表示取指針指向變量地址的值&a為變量a的地址;*pa為指針變量指向變量a的存儲單元注:
1.把一個變量的內(nèi)存地址作為初始值賦給指針時,該變量必須在指針初始化之前已經(jīng)說明過(變量只有在說明之后才被分配一定的內(nèi)存地址)。把一個指針初始化為空指針:
int*px=0;或int*px=NULL;
稱指針px為空指針。表示當(dāng)前該指針并不指向該類型的任何一個變量(對象)。2.該變量的數(shù)據(jù)類型必須與指針的數(shù)據(jù)類型一致。為使用安全起見,一般來說,在定義指針時,最好初始化(如,初始化為空指針)。3.如果在定義指針時,指針初始化為0或者根本沒有初始化。則在使用此指針前,就必須給它賦有意義的值。例:
intn,*p1;
//定義指針p1時沒有初始化
p1=&n;
//給指針p1賦值為int型變量n的地址或者:
intn,*p1=0;
//定義指針p1時初始化為0
p1=&n;
//給指針p1賦值為int型變量n的地址
C++編譯系統(tǒng)為每一個指針變量分配4個字節(jié)的存儲單元,用來存放變量的地址。在定義指針變量時要注意:
(1)慎用指針——對指針變量絕不可任意賦一個內(nèi)存地址。如
int*P=(int*)0xaf80;(2)在定義指針變量時必須指定基類型。
一個指針變量只能指向同一個類型的變量。(不同類型數(shù)據(jù)在計算機中存儲方式和所占的字節(jié)數(shù)不同)例:一個指向整數(shù)類型的指針變量,如果使指針值加1,意味使地址值加4,一個指向雙精度類型的指針變量,如果使指針值加1,意味使地址值加8。(3)常量是不可尋址的,p_age=&20是錯的。但常變量是可尋址的,如:
constfloatPI=3.14159;float*pointer=&PI;(4)指針的類型可以強制轉(zhuǎn)換,有特殊應(yīng)用,例:
intm,*pm=&m;char*p1=(char*)&m,*p2=(char*)pm;
用pm讀的是整型數(shù),用p1,p2讀的是整型數(shù)的第一個字節(jié)。
C語言的指針容易失控,在C++中增加了引用類型,它具有指針的主要功能,但限制了靈活性,使用更加安全。建議在函數(shù)參數(shù)傳遞中,能用“引用”時絕不用“指針”。20age218age1p_age#include<iostream>
usingnamespacestd;
int
main(){
intage1=18,age2=20,*p_age;
p_age=&age1;//情況1,見圖
cout<<"ageofwangpingis“<<*p_age<<endl;
p_age=&age2;//情況2
cout<<"ageofzhanglingis"<<*p_age<<endl;
return0;}注意:指針變量p_age在定義說明時要加“*”,這里“*”為說明符;而在可執(zhí)行語句中p_age不用也不允許加“*”號。在可執(zhí)行語句中“*”為間接引用運算符,*p_age代表p_age所指向的在內(nèi)存中可尋址的數(shù)據(jù)。在上例中最后的*p_age就是age2?!纠?.6】指針賦值實例指針的關(guān)系運算:兩個指針變量的關(guān)系運算是根據(jù)兩個指針變量值的大小(作為無符號整數(shù))來進行比較的(限同類型的指針變量)。注:
1.比較兩個指針變量相等,是判斷兩個指針變量是否指向相同的內(nèi)存單元,即兩個指針值是否相同。
2.不等比較,是判斷兩個指針是否指向不同的內(nèi)存單元。
3.當(dāng)指針變量與0比較時,表示指針變量的值是否為空。注意:C++編譯器只對指針的運算作語法上的檢查,不管指針的使用是否正確。指針的正確必須由程序的設(shè)計者自己來保證。
C++中,同一個符號可能表示不同的運算符。如:“*”既表示乘法運算符又表示指針運算符,“&”可表示“按位與”又可表示取地址運算符。所有運算符按規(guī)定的優(yōu)先級操作:(1)運算符“*”和“&”,優(yōu)先級相同,按自右向左方向例:
inta=3;
int*p1,*p2;p1=&a;p2=&*p1;//將a的地址賦給p2,使p2指向ap2=&*p1;&a&bp1p210010abp1&ap2&ba100b10p2=&a*&a的含義,先進行&a的運算,得到a的地址,再進行*運算,即&a所指向的變量。
\*&a和*pointer_1的作用相同等價于變量a。設(shè)已執(zhí)行:pointer_1=&a;則*&a與a等價。例:輸入a和b兩個整數(shù),按先大后小的順序輸出a和bintmain(){
int*p1,*p2,*p,a,b;
cin>>a>>b;p1=&a;//使p1指向ap2=&b;//使p2指向bif(a<b){//如果a<b就使p1與p2的值交換
p=p1;p1=p2;p2=p;//交換p1與p2的指向
}
cout<<″a=″<<a<<″b=″<<b<<endl;
cout<<″max=″<<*p1<<″min=″<<*p2<<endl;return0;}輸入:4578
輸出:a=45b=78max=78min=45&a&bp1p24578abp1&bp2&aa45b78p1=&a;//把變量a的地址賦給p1p2=&b;//把變量a的地址賦給p2if(a<b){p=p1;p1=p2;p2=p;}
//地址交換指針常量:指針常量是固定指向一個對象的指針,即指針本身是常量:
charch=’a’,ch1=’x’;
char*const
ptr=&ch;//注意const放在類型說明之后,變量名之前*ptr=’b’;//正確
ptr=&ch1;//錯誤
ptr本身在初始化時所指向的地址是不可改變的,但它指向的目標(biāo)ch的值是可以改變的。常量指針:
常量指針是指向“常量”的指針,即指針本身可以改指向別的對象,但不能通過該指針修改對象,該對象可以通過其他方式修改,常用于函數(shù)的參數(shù),以免誤改了實參。charch=’a’,ch1=’x’;constchar*ptr1=&ch;
//ptr1是常量指針*ptr1=’b’;
//錯誤,只能做ch=’b’ptr1=&ch1;
//正確4.4
引用4.4.1引用值傳遞指主調(diào)函數(shù)向被調(diào)函數(shù)傳遞的是實參的值。當(dāng)向被調(diào)函數(shù)傳遞一個變量的數(shù)據(jù)時,系統(tǒng)為每一個形參變量分配相應(yīng)的臨時存儲空間,調(diào)用函數(shù)的實參值就復(fù)制在對應(yīng)的形參的臨時存儲空間中。被調(diào)函數(shù)只對形參的臨時存儲空間發(fā)生作用,不對實參本身進行操作。問題:如果要求改變實參的值,怎么辦呢?如果實參是一個復(fù)雜的對象,重新分配內(nèi)存會引起程序執(zhí)行效率下降,怎么辦呢?有一種導(dǎo)出型數(shù)據(jù)類型—引用(reference)可以解決上面的難題。引用又稱別名(alias)。引用的定義:
引用是給一個已經(jīng)定義的變量重新起一個別名,而不是定義一個新的變量,定義的格式為:
類型&引用變量名=已定義過的變量名;例:
inta;//定義a是整型變量
int&b=a;//聲明b是a的引用
b是新定義的引用類型變量,是變量a的別名。
聲明后,a或b的作用相同,都代表同一變量。(b和a占用內(nèi)存中的同一個存儲單元,地址相同,不另占空間)a=20;b=a;聲明一個引用型變量時,必須同時使之初始化,即聲明它代表哪一個變量,并且從此不可改變。變量名和引用名都指向同一段內(nèi)存單元。如果形參為變量的引用名,實參為變量名,則在調(diào)用函數(shù)進行虛實結(jié)合時,并不是為形參另外開辟一個存儲空間(常稱為建立實參的一個拷貝),而是把實參變量的地址傳給形參(引用名),這樣引用名也指向?qū)崊⒆兞?。一個變量的引用就是變量的別名。引用主要用于函數(shù)之間的數(shù)據(jù)傳遞?!纠?.3】引用作為形參Xy1.4142.7181.4142.7181.414
voidswap(double&d1,
double&d2){
doubletemp;temp=d1;d1=d2;d2=temp;}int
main(void){
doublex,y;
cout<<"請輸入x和y的值"<<'\n';
cin>>x>>y;
swap(x,y);
cout<<"x="<<x<<'\t'<<"y="<<y<<'\n';
return0;}圖5.5參數(shù)d1、d2為引用時內(nèi)存分配示意
d1d2temp實參傳值,形參別名#include<iostream.h>voidmain(){voidswap(int*,int*);
inti=3,j=5;swap(&i,&j);//實參是變量的地址
cout<<i<<″″<<j<<endl;//i和j的值已互換}voidswap(int*p1,int*p2){//形參是指針變量
inttemp;temp=*p1;//以下3行用來實現(xiàn)i和j的值互換*p1=*p2;*p2=temp;}實參傳地址,形參指針指向變量地址例:對3個變量按由小到大的順序排序。intmain(){ voidsort(int&,int
&,int&);
//函數(shù)聲明,形參是引用類型
inta,b,c;
//a,b,c是需排序的變量
inta1,b1,c1;
//a1,b1,c1最終的值是已排好序的數(shù)列
cout<<″Pleaseenter3integers:″;
cin>>a>>b>>c;
a1=a;b1=b;c1=c;
sort(a1,b1,c1);
//調(diào)用sort函數(shù),以a1,b1,c1為實參
cout<<″sortedorderis″<<a1<<″″<<b1<<″″<<c1<<endl;//此時a1,b1,c1已排好序
return0;}voidsort(int&i,int&j,int&k){
//對i,j,k3個數(shù)排序
voidchange(int&,int&);
//函數(shù)聲明,形參是引用類型
if(i>j)change(i,j);
//使i<=j if(i>k)change(i,k);
//使i<=k if(j>k)change(j,k);
//使j<=k}voidchange(int&x,int&y)
{
//使x和y互換
inttemp; temp=x; x=y; y=temp;}運行結(jié)果:
Pleaseenter3integers:2312-345↙sortedorderis-3451223
【例4.4】采用不同返回方式的求正方形面積函數(shù)的比較。double
temp;//全局變量doublefsqr1(doublea){
temp=a*a;return
temp;}double&fsqr2(doublea){
temp=a*a;returntemp;}intmain(){
doublex=fsqr1(5.5);//第一種情況
doubley=fsqr2(5.5);//第二種情況
cout<<"x="<<x<<'\t‘<<"y="<<y<<endl;
return0;}引用作為返回值運行結(jié)果為:
x=30.25y=30.25運行結(jié)果一樣,但在內(nèi)存中的活動卻不同。
圖4.6普通返回
圖4.7引用返回函數(shù)fsqr1返回全局變量temp,是先將temp的值賦值給那個無名臨時變量,回到主函數(shù)后,賦值語句x=fsqr1(5.5)把臨時變量的值賦給x,無名臨時變量生命期結(jié)束。沒有使用無名臨時變量過渡,而是直接返回temp本身,賦給y。無名臨時變量中放的是temp的地址。不產(chǎn)生拷貝,效率提高了。注:采用引用返回方式時,返回的不能是函數(shù)中的局部變量(此時返回的局部變量地址已失效)。5.5數(shù)組與指針5.5.1數(shù)組名、指針和指針運算5.5.2指針作為函數(shù)參數(shù)5.5.1數(shù)組名、指針和指針運算數(shù)組名和指針的關(guān)系:數(shù)組名是一個指針常量a[0]a[1]a[2]a[3]a[4]a[5]inta[6];int*p=&a[0];p指針指向數(shù)組后,可以像數(shù)組名一樣使用:for(inti=0;i<6;i++)cin>>a[i];for(inti=0;i<6;i++)cout<<p[i]<<‘\t’;ints=0;for(inti=0;i<6;i++)s=s+*p++;//或*(a+i)
p=a;for(inti=0;i<6;i++)cin>>*(p+i);//或*(a+i)
//等價于p=a;指針的算術(shù)運算:(1)++或--運算
<指針變量>++;<指針變量>--;
計算機內(nèi)部按下式計算:
<指針變量>=<指針變量>+sizeof(<指針變量類型>)<指針變量>=<指針變量>-sizeof(<指針變量類型>)指針變量的值加或減一個常量。指針變量的值加一個常量n,類同于++運算,計算機的實際運算為:<指針變量>=<指針變量>+sizeof(<該指針變量的類型>)*n;例:intmain(){
inta[10]={100,200,300,400,500};
int*p1=&a[0];
cout<<"*p1="<<*p1<<"\tp1="<<(int)p1<<endl; p1=p1+4;
cout<<"*p1="<<*p1<<"\tp1="<<(int)p1<<endl;return0;}*p1=100p1=1310552*p1=500p1=1310568*P++:取P所指向單元的數(shù)據(jù)作為表達(dá)式的值,然后使
P指向下一個單元;(*P)++:
取P所指向單元的數(shù)據(jù)作為表達(dá)式的值,然后使
該單元的數(shù)據(jù)值增加1;*++P:使P指向下一個單元,然后取該單元的數(shù)據(jù)作為表達(dá)式的值;++*P:將P所指向單元的數(shù)據(jù)增加1并作為表達(dá)式的值。指針的算術(shù)運算:(3)“++”、“--”、“*”、“&”的優(yōu)先級相同,按自右向左方向結(jié)合。例:inta[5]={100,200,300,400,500};p1=&a[0],b=*p1++;
//取*p1的值參加運算,再使指針p1的值加1,b的值為100
p1=&a[0],b=*++p1;
//先使指針p1的值加1,再取*p1的值參加運算,b的值為200
p1=&a[0],b=(*p1)++;
//先取*p1的值參加運算,再完成*p1的值加1,b的值為100*(p1++);
等價于
*p++;
p1=&a[1],b=++*p1;
//取出p1所指向的內(nèi)容,使其加1后參加接著的運算,b的值為201//a[1]的值修改為201,p1仍然指向數(shù)組a的第一個元素。如果指針p的初值為&a[0]:
(1)p+i和a+i就是a[i]的地址,或者說,它們指向a數(shù)組的第i個元素。(2)*(p+i)或*(a+i)是p+i或a+i所指向的數(shù)組元素,即a[i]。(3)指向數(shù)組元素的指針變量也可以帶下標(biāo),如p[i]和*(p+i)等價。引用一個數(shù)組元素,可用以下方法:(1)下標(biāo)法,如a[i]形式;若已使p的值為a,則*(p+i)就是a[i]。可以通過指向數(shù)組元素的指針找到所需的元素。(2)指針法,如*(a+i)或*(p+i)。其中a是數(shù)組名,p是指向數(shù)組元素的指針變量。直觀不必每次都重新計算地址,提高執(zhí)行效率例:
設(shè)有一個int型數(shù)組,有10個元素。用三種方法輸出各元素。intmain(){
inta[10],i;
for(i=0;i<10;i++)cin>>a[i];
for(i=0;i<10;i++)cout<<a[i]<<″″;
cout<<endl;return0;}1.使用數(shù)組名和下標(biāo)2.使用數(shù)組名和指針運算intmain(){
inta[10],i;
for(i=0;i<10;i++)cin>>*(a+i);
for(i=0;i<10;i++)cout<<*(a+i)<<″″;
cout<<endl;return0;}3.使用指針變量intmain(){
inta[10];
int*p;
for(p=a;p<(a+10);p++)cin>>*p;
for(p=a;p<(a+10);p++)
cout<<*p<<″″;
cout<<endl;return0;}intmain(){//例
inta[5]={100,200,300,400,500};
int*p1,*p2; for(p2=&a[0];p2<=&a[4];p2++)//p2指向a數(shù)組
cout<<*p2<<'\t';
cout<<endl; p1=&a[0]+5;//p1指向a數(shù)組后的地址單元
p2=&a[0];//p2指向a數(shù)組的首地址
intsum=0; while(p2!=p1){sum+=*p2++;}//累加
cout<<"元素之和為:"<<sum<<endl;return0;}輸出:100200300400500
元素之和為:15005.5.2指針作為函數(shù)參數(shù)
引用調(diào)用與指針傳值調(diào)用:建議:
在函數(shù)參數(shù)傳遞中,能用“引用”時絕不用“指針”。*參數(shù)傳遞兩種方法:傳值、傳引用。*傳指針作為特殊的傳值調(diào)用,使得形參獲得實參地址,能夠直接訪問并修改實參數(shù)據(jù)。*傳引用邏輯上稱為別名,物理上是傳實參的地址。intmain(){
int*pointer_1,*pointer_2,a,b;
cin>>a>>b;pointer_1=&a;//使pointer_1指向apointer_2=&b;//使pointer_2指向bif(a<b)swap(pointer_1,pointer_2);//如果a<b,使*pointer_1和*pointer_2互換
cout<<″max=″<<a<<″min=″<<b<<endl;//a已是大數(shù),b是小數(shù)
return0;}voidswap(int*p1,int*p2){//將*p1的值與*p2的值交換
inttemp;temp=*p1;*p1=*p2;*p2=temp;}交換a和b的值,p1和p2的值不變不能寫成:int*temp;*temp=*p1;*p1=*p2;*p2=*temp;主函數(shù)swap(pointer_1,pointer_2)p1p2結(jié)果如果希望通過函數(shù)調(diào)用得到n個要改變的值步驟:①在主調(diào)函數(shù)中設(shè)n個變量,用n個指針變量指向它們;②被調(diào)用函數(shù)的形參為n個指針變量(與實參類型相同);③在主調(diào)函數(shù)中將n個指針變量作實參,將它們的值(是地址值)傳給所調(diào)用函數(shù)的n個形參指針變量。則,形參指針變量也指向這n個變量;④通過形參指針變量的指向,改變該n個變量的值;⑤在主調(diào)函數(shù)中就可以使用這些改變了值的變量。intmain(){voidswap(int*p1,int*p2);
int*pointer_1,*pointer_2,a,b;
cin>>a>>b;pointer_1=&a;pointer_2=&b;if(a<b)swap(pointer_1,pointer_2);
cout<<″max=″<<a<<″min=″<<b<<endl;return0;}voidswap(int*p1,int*p2){
int*temp;temp=p1;p1=p2;p2=temp;}p1、p2指向的地址改變,a、b的值沒變p1、p2指向的地址交換if(a<b)swap(pointer_1,pointer_2);voidswap(int*p1,int*p2){int*temp;temp=p1;p1=p2;p2=temp;}實參和形參之間的數(shù)據(jù)傳遞是單向的“值傳遞”方式。調(diào)用函數(shù)時不會改變實參指針變量的值,但可以改變實參指針變量所指向變量的值。使用指針變量作函數(shù)參數(shù),可以通過指針變量改變主調(diào)函數(shù)中變量的值,相當(dāng)于通過函數(shù)調(diào)用從被調(diào)用的函數(shù)中得到多個值。例輸入a,b,c3個整數(shù),按由大到小的順序輸出。intmain(){voidexchange(int*,int*,int*);//對exchange函數(shù)的聲明
inta,b,c,*p1,*p2,*p3;
cin>>a>>b>>c;p1=&a;p2=&b;p3=&c;//指向3個整型變量
exchange(p1,p2,p3);//交換p1,p2,p3指向的3個整型變量的值
cout<<a<<″″<<b<<″″<<c<<endl;//按由大到小的順序輸出3個整數(shù)
return0;}voidexchange(int*q1,int*q2,int*q3){voidswap(int*,int*);
//對swap函數(shù)的聲明
if(*q1<*q2)swap(q1,q2);
//調(diào)用swap,將q1與q2所指向的變量的值互換
if(*q1<*q3)swap(q1,q3);
//調(diào)用swap,將q1與q3所指向的變量的值互換
if(*q2<*q3)swap(q2,q3);
//調(diào)用swap,將q2與q3所指向的變量的值互換}voidswap(int*pt1,int*pt2){//將pt1與pt2所指向的變量的值互換
inttemp;temp=*pt1;*pt1=*pt2;*pt2=temp;}運行結(jié)果:
12-5687↙
//輸入
8712-56//輸出實參與形參的結(jié)合,有4種形式:
inta[5]={1,2,3,4,5};
int*p=a;fun();
實參
形參數(shù)組名fun(a); 數(shù)組名fun(ints[])
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 第5單元 走向近代【考題猜想】(純試題)-2023-2024學(xué)年九年級歷史上學(xué)期期中考點大串講(部編版)
- 課題申報參考:面向最后一公里配送的無人機集貨中心選址及任務(wù)分配研究
- 二零二五年度米廠水稻種植與農(nóng)村電商合作項目合同4篇
- 2025年度餐飲店承包經(jīng)營與食品安全責(zé)任合同
- 2025年度個人虛擬形象設(shè)計制作合同樣本4篇
- 2025年度二零二五年度木材加工廢棄物處理合同規(guī)范4篇
- 二零二五版木制托盤庫存管理與采購合同4篇
- 2025年度個人貨運車輛保險合同范本大全3篇
- 二零二五年度玻璃瓶罐生產(chǎn)與銷售采購合同3篇
- 2025年度文化旅游項目承包商擔(dān)保合同范本4篇
- 《職業(yè)培訓(xùn)師教程》課件
- (康德一診)重慶市2025屆高三高三第一次聯(lián)合診斷檢測 英語試卷(含答案詳解)
- 2025年福建泉州文旅集團招聘24人高頻重點提升(共500題)附帶答案詳解
- 文化沖突與民族認(rèn)同建構(gòu)-洞察分析
- 《疥瘡的防治及治療》課件
- 學(xué)校對口幫扶計劃
- 腫瘤全程管理
- 《3-6歲兒童學(xué)習(xí)與發(fā)展指南》專題培訓(xùn)
- 導(dǎo)尿及留置導(dǎo)尿技術(shù)
- 2024年高中一年級數(shù)學(xué)考試題及答案
- 寒假作業(yè)一年級上冊《數(shù)學(xué)每日一練》30次打卡
評論
0/150
提交評論