1. 程式人生 > >二維陣列與指標、指標陣列、陣列指標的用法

二維陣列與指標、指標陣列、陣列指標的用法

二維陣列和指標⑴ 用指標表示二維陣列元素。
要用指標處理二維陣列,首先要解決從儲存的角度對二維陣列的認識問題。我們知道,一個二維陣列在計算機中儲存時,是按照先行後列的順序依次儲存的,當把每一行看作一個整體,即視為一個大的陣列元素時,這個儲存的二維陣列也就變成了一個一維陣列了。而每個大陣列元素對應二維陣列的一行,我們就稱之為行陣列元素,顯然每個行陣列元素都是一個一維陣列

下面我們討論指標和二維陣列元素的對應關係,清楚了二者之間的關係,就能用指標處理二維陣列了。
設p是指向二維陣列a[m][n]的指標變數,則有:

int* p=a[0];//此時P是指向一維陣列的指標。P++後,p指向 a[0][1]。

如果定義int (*p1)[n];p1=a;p1++後,p1指向a[1][0];  

則p+j將指向a[0]陣列中的元素a[0][j]。
由於a[0]、a[1]┅a[M-1]等各個行陣列依次連續儲存,則對於a陣列中的任一元素a[i][j],指標的一般形式如下:
p+i*N+j             相應的如果用p1來表示,則為*(p1+i)+j
元素a[i][j]相應的指標表示為:
*( p+i*N+j)        相應的如果用p1來表示,則為*(*(p1+i)+j)
同樣,a[i][j]也可使用指標下標法表示,如下:
p[i*N+j]
例如,有如下定義:
int a[3][4]={{10,20,30,40,},{50,60,70,80},{90,91,92,93}};
則陣列a有3個元素,分別為a[0]、a[1]、a[2]。而每個元素都是一個一維陣列,各包含4個元素,如a[1]的4個元素是a[1][0]、a[1][1]、a[1]2]、a[1][3]。
若有:
int *p=a[0];
則陣列a的元素a[1][2]對應的指標為:p+1*4+2
元素a[1][2]也就可以表示為:*( p+1*4+2)
用下標表示法,a[1][2]表示為:p[1*4+2]
特別說明:
對上述二維陣列
a,雖然a[0]、a都是陣列首地址,但二者指向的物件不同,a[0]是一維陣列的名字,它指向的是a[0]陣列的首元素,對其進行“*”運算,得到的是一個數組元素值,即a[0]陣列首元素值,因此,*a[0]與a[0][0]是同一個值;而a是一個二維陣列的名字,它指向的是它所屬元素的首元素,它的每一個元素都是一個行陣列,因此,它的指標移動單位是“行”,所以a+i指向的是第i個行陣列,即指向a[i]。對a進行“*”運算,得到的是一維陣列a[0]的首地址,即*a與a[0]是同一個值。當用int *p;定義指標p時,p的指向是一個int型資料,而不是一個地址,因此,用a[0]對p賦值是正確的,而用a對p賦值是錯誤的。這一點請讀者務必注意。
⑵ 用二維陣列
名作地址表示陣列元素。
另外,由上述說明,我們還可以得到二維陣列元素的一種表示方法:
對於二維陣列a,其a[0]陣列由a指向,a[1]陣列則由a+1指向,a[2]陣列由a+2指向,以此類推。因此,*a與a[0]等價、*(a+1)與a[1]等價、*(a+2)與a[2]等價,┅,即對於a[i]陣列,由*(a+i)指向。由此,對於陣列元素a[i][j],用陣列名a的表示形式為:
*(*(a+i)+j)
指向該元素的指標為:
*(a+i)+j

陣列名雖然是陣列的地址,但它和指向陣列的指標變數不完全相同。

第一,指標變數的值可以改變,即它可以隨時指向不同的陣列或同類型變數,而陣列名自它定義時起就確定下來,不能通過賦值的方式使該陣列名指向另外一個數組。

第二,陣列名是指標,型別是指向元素型別的指標,但值是指標常量,宣告陣列時編譯器會為宣告所指定的元素數量保留記憶體空間。陣列指標是指向陣列的指標,宣告指標變數時編譯器只為指標本身保留記憶體空間。

例4 求二維陣列元素的最大值。


該問題只需對陣列元素遍歷,即可求解。因此,可以通過順序移動陣列指標的方法實現。
main()
{
int a[3][4]={{3,17,8,11},{66,7,8,19},{12,88,7,16}};
int *p,max;
for(p=a[0],max=*p;p<a[0]+12;p++)
   if(*p>max)
      max=*p;
printf("MAX=%d/n",max);
}
執行結果:
MAX=88
這個程式的主要演算法都是在for語句中實現的:p是一個int型指標變數;p=a[0]是置陣列的首元素地址為指標初值;max=*p將陣列的首元素值a[0][0]作為最大值初值;p<a[0]+12是將指標的變化範圍限制在12個元素的位置內;p++使得每比較一個元素後,指標後移一個元素位置。
例5 求二維陣列元素的最大值,並確定最大值元素所在的行和列。
本例較之上例有更進一步的要求,需要在比較的過程中,把較大值元素的位置記錄下來,顯然僅用上述指標移動方法是不行的,需要使用能提供行列資料的指標表示方法。
main()
{
int a[3][4]={{3,17,8,11},{66,7,8,19},{12,88,7,16}};
int *p=a[0],max,i,j,row,col;
max=a[0][0];
row=col=0;
for(i=0;i<3;i++)
   for(j=0;j<4;j++)
     if(*(p+i*4+j)>max)
      {
        max=*(p+i*4+j);
        row=i;
        col=j;
      }
printf("a[%d][%d]=%d/n",row,col,max);
}
程式執行結果:
a[2][1]=88
⑶ 行陣列指標
在上面的說明中我們已經知道,二維陣列名是指向行的,它不能對如下說明的指標變數p直接賦值:
int a[3][4]={{10,11,12,13},{20,21,22,23},{30,31,32,33}},*p;
其原因就是p與a的物件性質不同,或者說二者不是同一級指標。C語言可以通過定義行陣列指標的方法,使得一個指標變數與二維陣列名具有相同的性質。行陣列指標的定義方法如下:
資料型別 (*指標變數名)[二維陣列列數];
例如,對上述a陣列,行陣列指標定義如下:
int (*p)[4];
它表示,陣列*p有4個int型元素,分別為(*p)[0]、(*p)[1]、(*p)[2]、(*p)[3] ,亦即p指向的是有4個int型元素的一維陣列,即p為行指標

此時,可用如下方式對指標p賦值:

p=a;

(4)指標陣列的定義

指標陣列是指每個元素中存放的是指標。定義為 int *p[4];sizeof(p)=16,返回的是陣列的總空間