?? 指針與數組.txt
字號:
7.2 指針與數組
由上節的例 7.4可知,可用指針變量來訪問數組中任一元素,通常將數組的首地址稱為數組的指針,而將指向數組元素的指針變量稱為指向數組的指針變量。使用指向數組的指針變量來處理數組中的元素,不僅可使程序緊湊,而且還可提高程序的運算速率。
7.2.1 一維數組與指針
1.數組指針
數組的首地址稱為數組指針。若定義整型數組a[5],系統為數組分配的地址從1000到1019,如圖7.5所示,則數組a的首地址1000為數組a的數組指針。C++規定,數組的首地址可用數組名a表示,因此,數組a的數組指針=a=&a[0]。
2.數組指針變量
存放數組元素地址的變量稱為數組指針變量。如:
int a[5];
int *p=&a[0];
則p為數組指針變量。在C++中數組名a可用于表示數組的首地址,所以數組名a可作為數組指針使用。因此:p=a與p=&a[0] 的作用是相同的。但數組名a不能用來進行賦值運算、"++"、"- -"等運算。
當指針變量指向數組首地址后,就可使用該指針變量對數組中任何一個元素變量進行存取操作。現舉例說明如下:
【例7.6】用指針變量訪問數組元素。
# include <iostream.h>
void main( void)
{ int a[5]={0,1,2,3,4},i,j,*p,n=5;
p=a;
for (i=0;i<n;i++)
{ cout <<*p<<'\t';
p++;
}
cout<<endl;
p=a;
for (i=0;i<n;i++) cout <<*(p+i)<< '\t';
cout<<endl;
for (i=0;i<n;i++) cout <<*(a+i)<< '\t';
cout<<endl;
for (i=0;i<n;i++) cout <<p[i]<< '\t';
cout<<endl;
}
執行程序后,輸出:
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
由上例可以看出,訪問數組元素值有三種方法:
(1)通過移動指針變量,依次訪問數組元素。如:
p=a;
for (i=0;i<n;i++)
{ cout <<*p<<'\t'; p++;}
首先將指針變量p指向數組a的首地址。然后用*p輸出數組第i個元素的值,每次輸出后用p++移動指針到下一個元素,依次循環直到結束。注意:cout <<*p<<'\t'; p++;可合并為一條語句:cout<<*p++<<'\t';
(2)指針變量不變,用p+i或 a+i 訪問數組第i個元素。如:
for (i=0;i<n;i++) cout <<*(p+i)<< '\t';
for (i=0;i<n;i++) cout <<*(a+i)<< '\t';
在C++中允許用p+i 或a+i 表示第i 個元素的地址。因此,*(p+i)與*(a+i)均表示第i個元素的內容。
(3)以指針變量名作為數組名訪問數組元素。如:
for (i=0;i<n;i++) cout <<p[i]<< '\t';
若用指針變量名p作為數組名,則p[i]表示數組的第i個元素a[i]。
3.數組元素的引用
綜上所述,對一維數組a[ ]而言,當p=a后,有如下等同關系成立:
① p+i=a+i=&a[i],即p+i、a+i 均表示第i個元素的地址&a[i]。
② *(p+i) =*(a+i)=p[i]= a[i]。即*(p+i), *(a+i), p[i]均表示第i個元素值a[i]。
其中p[i] 的運行效率最高。
由上所述可知:一維數組的第i個元素可用四種方式引用,即: a[i]、*(p+i) 、*(a+i)、p[i]。
7.2.2 二維數組與指針
1.二維數組元素在內存中的存放方式
在C++中,二維數組元素值在內存中是按行的順序存放的。若定義二維整型數組a[3][3],假設編譯系統為數組a分配的內存空間從1000開始到1035為止,則數組中各元素a[0][0]~a[2][2]在內存中按行存放次序如圖7.6所示。因此,與一維數組類似,可用指針變量來訪問二維數組元素。
【例7.7】用指針變量輸出二維數組各元素的值。
# include <iostream.h>
void main(void)
{ int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
int *p=&a[0][0]; //將二維數組首地址賦給指針變量p
for (int i=0;i<9;i++)
{ cout<<*p<<'\t'; //輸出二維數組中第i個元素值
p++; //指針變量p加1,指向下一個元素
}
}
程序執行后輸出結果為:
1 2 3 4 5 6 7 8 9
但要用上述指針變量p訪問二維數組中任意指定元素a[i][j]就覺得很不方便,為此C++設計者提供另外幾種訪問二維數組元素的方法,為了了解訪問二維數組元素的方法,必須了解三個地址概念,即:二維數組行首地址、行地址、元素地址,現介紹如下。
2.二維數組行首地址
二維數組各元素按行排列可寫成如圖7.7所示矩陣形式,若將第i行中的元素a[i][0]、a[i][1]、a[i][2]組成一維數組a[i] (i=0,1,2),則二維數組a[3][3]可看成是由三個一維數組元素a[0]、a[1]、a[2]組成。即:a[3][3]=(a[0],a[1],a[2]),其中:a[0]、a[1]、a[2]是分別表示二維數組a[3][3]的第0、1、2行元素。
即:a[0]=(a[0][0],a[0][1],a[0][2])
a[1]=(a[1][0],a[1][1],a[1][2])
a[2]=(a[2][0],a[2][1],a[2][2])
因為數組名可用來表示數組的首地址,所以一維數組名a[i]可表示一維數組 (a[i][0],a[i][1],a[i][2])的首地址&a[i][0],即可表示第i行元素的首地址。因此,二維數組a中第i行首地址(即第i行第0列元素地址)可用a[i]表示。
由例 7.6可知,一維數組的第i個元素地址可表示為:數組名+i。因此一維數組a[i]中第j個元素a[i][j]地址可表示為:a[i]+j ,即:二維數組a中第i行第j列元素a[i][j]的地址可用a[i]+j來表示,而元素a[i]][j]的值為:*(a[i]+j)。
【例7.8】定義一個3行3列數組,輸出每行的首地址及所有元素值。
# include <iostream.h>
void main(void)
{ int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
for (int i=0;i<3;i++)
{ cout<<"a[" <<i<<"]="<<a[i]<< "="<<&a[i][0]<<endl;
for (int j=0;j<3;j++)
cout<<"a[" <<i<<"]["<<j<<"]="<<*(a[i]+j)<< "="<<a[i][j]<<endl;
}
}
程序執行后輸出:
a[0]=0x0065FDD4=0x0065FDD4
a[0][0]=1=1
a[0][1]=2=2
a[0][2]=3=3
a[1]=0x0065FDE0=0x0065FDE0
a[1][0]=4=4
a[1][1]=5=5
a[1][2]=6=6
a[2]=0x0065FDEC=0x0065FDEC
a[2][0]=7=7
a[2][1]=8=8
a[2][2]=9=9
由此例輸出結果可看出a[i]=&a[i][0] (i=0,1,2),這表明a[i]確實可以表示第i行首地址(即第i行第0列地址)&a[i][0]。
讀者應注意,由于數組在內存的地址是由操作系統動態分配,因此,實際輸出的各行首地址并不會如圖7.5所假設的從1000到1035。通常地址用十六進制數表示,如在本例中:第0行實際首地址是:a[0]=0x0065FDD4。第1行實際首地址是:a[1]=0x0065FDE0。第2行實際首地址是:a[2]=0x0065FDEC。
3.二維數組行地址
為了區別數組指針與指向一維數組的指針,C++引入了行地址的概念,并規定二維數組a中第i行地址用a+i或&a[i]表示,行地址的值與行首地址的值是相同的,即:
a+i=&a[i]=a[i]=&a[i][0]
但兩者類型不同,所以行地址a+i與&a[i]只能用于指向一維數組的指針變量,而不能用于普通指針變量,例如:
int a[3][3];
int *p=a+0;
則編譯第二條指令時將會出錯,編譯系統提示用戶p與a+0的類型不同。如果要將行地址賦數組指針變量,必須用強制類型轉換,如:
int *p=(int *) (a+0);
關于指向一維數組的指針將在后文中介紹。
二維數組名a可用于表示二維數組的首地址,但C++規定該首地址并不是二維數組中第0行第0列的地址(即a≠a[0][0]),而是第0 行的行地址,即a=a+0=&a[0]。
4.二維數組的元素地址與元素值
知道了二維數組的行地址與行首地址后,可以討論二維數組的元素地址。
因為 a[i]=*&a[i]= *(a+i),所以 *(a+i) 可以表示第 i行的首地址。因此二維數組第i行首地址有三種表示方法:a[i] 、*(a+i)、&a[i][0]。
由此可推知:第i行第j列元素a[i][j]的地址有四種表示方法:
a[i]+j 、*(a+i)+j、&a[i][0]+j、&a[i][j]
而第i行第j列元素a[i][j]值也有四種表示方法:
*(a[i]+j) 、 *(*(a+i)+j)、*(&a[i][0]+j)、a[i][j]
現將二維數組有關行地址、行首地址、元素地址、元素值的各種表示方式總結歸納如表7.1 所示:
表7.1 二維數組a的行地址、行首地址、元素地址、元素值的各種表示方式
行地址、元素地址、元素值 表示方式
第i行行地址 a+i、&a[i]
第i行首地址(第i行第0列地址) a[i]、 *(a+i)、 &a[i][0]
元素a[i][j]的地址 a[i]+j 、*(a+i)+j 、&a[i][0]+j、&a[i][j]
第i行第j列元素值 *(a[i]+j) 、 *(*(a+i)+j) 、 *(&a[i][0]+j)、a[i][j]
為了加深讀者對二維數組a的行地址、行首地址、元素地址、元素值的各種表示方式的理解,現舉例如下:
【例7.9】定義二維數組a[3][3],用二種方式輸出行地址,用三種方式輸出行首地址,用四種方式輸出所有元素地址及元素值。
# include <iostream.h>
void main(void)
{ int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
for (int i=0;i<3;i++)
{ cout<<"&a["<<i<<"]="<<&a[i]<<"="<<a+i<<endl; //輸出第i行行地址
cout<<"a["<<i<<"]="<<a[i]<<"="<<*(a+i)<<"="<<&a[i][0]<<endl; //行首地址
for (int j=0;j<3;j++)
{ cout<<"&a["<<i<<"]["<<j<<"]="<<a[i]+j<<"="<<*(a+i)+j<<"="<<
&a[i][0]+j<<"="<<&a[i][j]<<endl; //輸出元素a[i][j]的地址
cout<<"a["<<i<<"]["<<j<<"]="<<*(a[i]+j)<<"="<<*(*(a+i)+j)<<
"="<<*(&a[i][0]+j)<<"="<<a[i][j]<<endl; //輸出元素a[i][j]的值
}
}
}
程序執行后輸出結果為:
&a[0]= 0x0065FDD4=0x0065FDD4
a[0]= 0x0065FDD4=0x0065FDD4=0x0065FDD4
&a[0][0]= 0x0065FDD4=0x0065FDD4=0x0065FDD4=0x0065FDD4
a[0][0]=1=1=1=1
&a[0][1]= 0x0065FDD8=0x0065FDD8=0x0065FDD8=0x0065FDD8
a[0][1]=2=2=2=2
&a[0][2]= 0x0065FDDC=0x0065FDDC=0x0065FDDC=0x0065FDDC
a[0][2]=3=3=3=3
&a[1]= 0x0065FDE0=0x0065FDE0
a[1]= 0x0065FDE0=0x0065FDE0=0x0065FDE0
&a[1][0]= 0x0065FDE0=0x0065FDE0=0x0065FDE0=0x0065FDE0
a[1][0]=4=4=4=4
&a[1][1]= 0x0065FDE4=0x0065FDE4=0x0065FDE4=0x0065FDE4
a[1][1]=5=5=5=5
&a[1][2]= 0x0065FDE8=0x0065FDE8=0x0065FDE8=0x0065FDE8
a[1][2]=6=6=6=6
&a[2]= 0x0065FDEC=0x0065FDEC
a[2]= 0x0065FDEC=0x0065FDEC=0x0065FDEC
&a[2][0]= 0x0065FDEC=0x0065FDEC=0x0065FDEC=0x0065FDEC
a[2][0]=7=7=7=7
&a[2][1]= 0x0065FDF0=0x0065FDF0=0x0065FDF0=0x0065FDF0
a[2][1]=8=8=8=8
&a[2][2]= 0x0065FDF4=0x0065FDF4=0x0065FDF4=0x0065FDF4
a[2][2]=9=9=9=9
此例可說明表7.1中的二維數組a的行地址、行首地址、元素地址、元素值的各種表示方式是正確的。
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -