一維數組的數組名是指向單個變量的指針。
二維數組的數組名是指向單個數組的指針(行指針)。
二維數組(如:a[3][4])的指針分為兩種:
1.行指針,如:a,是一個指向數組的指針;
2.列指針,如:&a[0][0],a[0],*a,是一個指向單個變量的指針。
雖然a,&a[0][0],a[0],*a,在物理上表示都是同一塊內存空間的地址,但在概念上它們的意義不同。
a表示的指針是指向整塊數組的。這時候我們把二維數組看作是數個一維數組組成的(如:a[3][4]是由三個一維數組組成的)。
&a[0][0],a[0],*a表示的指針是指向單個變量的。這時候我們把二維數組直接看做一維數組,元素像一維數組中一樣一個挨一個排列。
對a進行解引用(即:*a)仍然會得到一個指針(並且它們的地址值相同……)。
所以可以推測出,對一個行指針進行解引用只是改變了其概念而已(而不是訪問a中保存的地址所表示的內存空間),具體是指:原來它指向的是一個數組,解引用后指向這個數組中的第一個元素,如果再解引用你就可以訪問這個元素了。
總結:
a,&a[0][0],a[0],*a表示的都是指針,並且是同一塊內存的地址,但它們表示的意義是不同的。
a表示行指針(指向一個數組),*a,a[0],&a[0][0]表示列指針(這三個是等價的,都指向數組中的一個元素)。
以取a[2][1]的值為例:
如果是行指針,則先要對它進行解引用,變為一個列指針,然后在解引用得到其值(a[2][1]=*(*(a+2)+1))。
如果是列指針,則直接進行解引用即可(a[2][1]=*(*a+2*4+1))。
測試代碼如下:(int類型占四個字節的情況下)
1 #include<stdio.h> 2 int main() 3 { 4 int a[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 }; 5 //int* p1 = &a[0][0]; 6 //int *p1 = a[0]; 7 int* p1 = *a; //列指針,指向一個單個變量 8 int(*p2)[4] = a; //行指針,指向一個含有四個元素的數組 9 //以下代碼表明:a,a[0],*a,&a[0][0]都是指針,並且里面的值也是一樣的 10 printf("%p\n", a); 11 printf("%p\n", a[0]); 12 printf("%p\n", *a); 13 printf("%p\n", &a[0][0]); 14 putchar('\n'); 15 //以下代碼表明:a與*a,a[0],&a[0][0]的不同之處 16 printf("%p\n", a); 17 printf("%p\n", a + 1); //對一個行指針加一,地址值向后移動了十六位(四個整形變量所占的內存) 18 printf("%p\n", *a); 19 printf("%p\n", *a + 1); //對一個列指針加一,地址值向后移動了四位(一個整形變量所占的內存) 20 printf("%p\n", a[0]); 21 printf("%p\n", a[0] + 1); 22 printf("%p\n", &a[0][0]); 23 printf("%p\n", &a[0][0] + 1); 24 putchar('\n'); 25 //以下代碼表明:對行指針進行解引用,得到的仍是一個指針,但它不再是一個行指針了(變成了列指針) 26 printf("%p\n", *a); 27 printf("%p\n", *a + 1); 28 putchar('\n'); 29 //以下代碼為取a[2][1]的值 30 printf("%d\n", a[2][1]); 31 printf("%d\n", *(*(a + 2) + 1)); 32 printf("%d\n", *(*a + 2 * 4 + 1)); 33 }