二維數組和指針

二維數組和指針

二維數組和指針1、二維數組和數組元素的地址若有以下定義:int *p, a[3][4];
1)二維數組a由若干個一維數組組成在C語言中定義的二維數組實際上是一個一維數組,這個一維數組的每一個成員又是一個一維數組。如以上定義的a數組,則可視a數組由a[0]、a[1]、a[2]等三個元素組成,而a[0]、a[1]、a[2]等每個元素又分別是由4個整型元素組成的一維數組。可用a[0][0]、a[0][1]等來引用a[0]中的每個元素,其它依次類推。在第二節中已解釋過,C語言中,在函數體中或在函數外部定義的一維數組名是一個地址常量,其值爲數組第一個元素的地址,此地址的基類型就是數組元素的類型。在以上二維數組中,a[0]、a[1]、a[2]都是一維數組名,同樣也代表一個不可變的地址變量,其值依次爲二維數組每行第一個元素的地址,其基類型就是數組元素的類型。因此,對於二維數組,象a[0]++這樣的表達式是非法的。若有表達式a[0]+1,表達式中1的單位應當是2個字節。在以上定義中,指針變量p的基類型與a[i](0≤i<3)相同,因此,賦值語句p=a[i];是合法的。我們已知a[i]也可以寫成:*(a+i),故以上賦值語句也可寫成:p=*(a+i);。
2)二維數組名也是一個地址常量二維數組名同樣也是一個存放地址常量的指針,其值爲二維數組中第一個元素的地址。以上a數組,數組名a的值與a[0]的值相同,只是其基類型爲具有4個整型元素的數組類型。即a+0的值與a[0]的值相同,a+1的值與a[1]的值相同,a+2的值與a[2]的值相同,它們分別表示a數組中第零、第一、第二行的首地址。二維數組名應理解爲一個行指針。在表達式a+1中,數值1的單位應是4×2個字節,而不是2個字節。賦值語句p=a;是不合法的,因爲p和a的基類型不同。同樣,對於二維數組名a,也不可以進行a++,a=a+i等運算。
3)二維數組元素的地址二維數組元素的地址可以由表達式&a[i][j]求得;也可以通過每行的首地址來表示。以上二維數組a中,每個元素的地址可以通過每行的首地址:a[0]、a[1]、a[2]等來表示。如:地址&a[0][0]可以用a[0]+0來表示,地址&a[0][1]可以用a[0]+1表示;若0≤i<3、0≤j<4,則a[i][j]的地址可用以下五種表達式求得:(1)&a[i][j](2)a[i]+j(3)*(a+i)+j(4)&a[0][0]+4*i+j (5)a[0]+ 4*i+j
在以上表達式中a[i]、&a[0][0]、a[0]的基類型都是int類型,系統將自動據此來確定表達式中常量1的單位是2個字節。但是不可以把求a[i][j]地址的表達式寫成:a+4*i+j,因爲a的基類型是4個整型元素的數組類型,系統將自動據此來確定常量1的單位是8個字節。
2、通過地址來引用二維數組元素若有以下定義:int a[3][4],i,j;且當0≤i<3、0≤j<4,則a數組元素可用以下五種表達式來引用:(1)a[i][j](2)*(a[i]+j)(3)*(*(a+i)+j)(4)(*(a+i))[j](5)*(&a[0][0]+4*i+j)
在(2)中,表達式*(a[i]+j)中,因爲a[i]的基類型爲int,j的位移量爲2×j字節。
在(3)中,表達式*(*(a+i)+j)中,a的基類型爲4個元素的數組,i的位移量爲4×2×i字節;而*(a+i)的基類型爲int,j的位移量仍爲2×j字節。
在(4)中,*(a+i)外的一對圓括號不可少,若寫成:*(a+i)[j],因爲運算符[]的優先級高於*號,表達式可轉換成:*(*(a+i)+j)),即爲:*(*(a+i+j)),這時i+j將使得位移量爲4×2×(i+j)個字節,顯示然這已不是元素a[i][j]的地址。*(*(a+i+j))等價於*(a[i+j])、等價於:a[i+j][0],引用的是數組元素a[i+j][0],而不是a[i][j],很可能早已超出數組定義的範圍。
在(5)中,&a[0][0]+4*i+j代表了數組元素a[i][j]的地址,通過間址運算符*號,表達式*(&a[0][0]+4*i+j)代表了數組元素a[i][j]的存儲單元。
3、通過建立一個指針數組來引用二維數組元素若有以下定義:int *p[3], a[3][2], i,j ;在這裏,說明符*p[3]中,也遵照運算符的優先級,一對[]的優先級高於*號,因此p首先與[]結合,構成p[3],說明了p是一個數組名,系統將爲它開闢3個連續的存儲單元;在它前面的*號則說明了數組p是指針類型,它的每個元素都是基類型爲int的指針。若滿足條件:0≤i<3,則p[i]和a[i]的基類型相同,p[i]= a[i]是合法的賦值表達式。
若有以下循環:for(i=0; i<3; i++) p[i]= a[i];在這裏,賦值號右邊的a[i]是常量,表示a數組每行的首地址,賦值號左邊的p[i]是指針變量,循環執行的結果使p[0]、p[1]、p[2]分別指向a數組每行的開頭。這時,數組p和數組a之間的關係如圖9.6所示。
當p數組的每個元素已如圖9.6所示指向a數組每行的開頭時,則a數組元素a[i][j]的引用形式*(a[i]+ j)和*(p[i]+j)是完全等價的。由此可見,這時可以通過指針數組p來引用a數組元素,它們的等價形式如下:(1)*(p[i]+j) (2)*(*(p+i)+j) (3)(*(p+i))[j] (4)p[i][j] 不同的是:p[i]中的值是可變的,而a[i]中的值是不可變的。
圖9.64、通過建立一個行指針來引用二維數組元素若有以下定義:int a[3][2], (*prt)[2];在這裏,說明符(*prt)[2]中,由於一對圓括號的存在,所以*號首先與prt結合,說明prt是一個指針變量,然後再與說明符[2]結合,說明指針變量prt的基類型是一個包含有兩個int元素的數組。在這裏,prt的基類型與a的相同,因此prt=a;是合法的賦值語句。prt+1等價於a+1、等價於a[1]。當prt指向a數組的開頭時,可以通過以下形式來引用a[i][j]:(1) *(prt[i]+j) (2) *(*(prt+i)+j) (3)(*(prt+i))[j] (4) prt[i][j] 在這裏,prt是個指針變量,它的值可變,而a是一個常量。
附:
#include "stdio.h"
void disp(int (*a)[3])
{
    printf("%d",*(*(a+1)+1));
}
void main()
{
    int a[2][3];
    a[0][0]=1;
    a[0][1]=2;
    a[0][2]=3;
    a[1][0]=4;
    a[1][1]=5;
    a[1][2]=6;
    disp(&a[0]);//也可以寫作disp(a);
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章