1. 程式人生 > >陣列指標和指標陣列的區別

陣列指標和指標陣列的區別

一、指標陣列和陣列指標的記憶體佈局

初學者總是分不出指標陣列與陣列指標的區別。其實很好理解:
指標陣列:首先它是一個數組,陣列的元素都是指標,陣列佔多少個位元組由陣列本身的大小決定,每一個元素都是一個指標,在32 位系統下任何型別的指標永遠是佔4 個位元組。它是“儲存指標的陣列”的簡稱。
陣列指標:首先它是一個指標,它指向一個數組。在32 位系統下任何型別的指標永遠是佔4 個位元組,至於它指向的陣列佔多少位元組,不知道,具體要看陣列大小。它是“指向陣列的指標”的簡稱。


下面到底哪個是陣列指標,哪個是指標陣列呢:
A)
int *p1[10];
B)
int (*p2)[10];
每次上課問這個問題,總有弄不清楚的。這裡需要明白一個符號之間的優先順序問題。


“[]”的優先順序比“*”要高。p1 先與“[]”結合,構成一個數組的定義,陣列名為p1,int *修飾的是陣列的內容,即陣列的每個元素。那現在我們清楚,這是一個數組,其包含10 個指向int 型別資料的指標,即指標陣列。至於p2 就更好理解了,在這裡“()”的優先順序比“[]”高,“*”號和p2 構成一個指標的定義,指標變數名為p2,int 修飾的是陣列的內容,即陣列的每個元素。陣列在這裡並沒有名字,是個匿名陣列。那現在我們清楚p2 是一個指標,它指向一個包含10 個int 型別資料的陣列,即陣列指標。我們可以藉助下面的圖加深理解:

二、int (*)[10] p2-----也許應該這麼定義陣列指標

這裡有個有意思的話題值得探討一下:平時我們定義指標不都是在資料型別後面加上指標變數名麼?這個指標p2 的定義怎麼不是按照這個語法來定義的呢?也許我們應該這樣來定義p2:
   int (*)[10] p2;
int (*)[10]是指標型別,p2 是指標變數。這樣看起來的確不錯,不過就是樣子有些彆扭。其實陣列指標的原型確實就是這樣子的,只不過為了方便與好看把指標變數p2 前移了而已。你私下完全可以這麼理解這點。雖然編譯器不這麼想。^_^

三、再論a 和&a 之間的區別

既然這樣,那問題就來了。前面我們講過a 和&a 之間的區別,現在再來看看下面的程式碼:
int main()
{
   char a[5]={'A','B','C','D'};

   char (*p3)[5] = &a;
   char (*p4)[5] = a;
   return 0;
}
上面對p3 和p4 的使用,哪個正確呢?p3+1 的值會是什麼?p4+1 的值又會是什麼?毫無疑問,p3 和p4 都是陣列指標,指向的是整個陣列。&a 是整個陣列的首地址,a是陣列首元素的首地址,其值相同但意義不同。在C 語言裡,賦值符號“=”號兩邊的資料型別必須是相同的,如果不同需要顯示或隱式的型別轉換。p3 這個定義的“=”號兩邊的資料型別完全一致,而p4 這個定義的“=”號兩邊的資料型別就不一致了。左邊的型別是指向整個陣列的指標,右邊的資料型別是指向單個字元的指標。在Visual C++6.0 上給出如下警告:
   warning C4047: 'initializing' : 'char (*)[5]' differs in levels of indirection from 'char *'。
還好,這裡雖然給出了警告,但由於&a 和a 的值一樣,而變數作為右值時編譯器只是取變數的值,所以執行並沒有什麼問題。不過我仍然警告你別這麼用。

既然現在清楚了p3 和p4 都是指向整個陣列的,那p3+1 和p4+1 的值就很好理解了。

但是如果修改一下程式碼,把陣列大小改小點,會有什麼問題?p3+1 和p4+1 的值又是多少呢?
int main()
{
   char a[5]={'A','B','C','D'};
   char (*p3)[3] = &a;
   char (*p4)[3] = a;
   return 0;
}

甚至還可以把程式碼再修改,把陣列大小改大點:
int main()
{
   char a[5]={'A','B','C','D'};
   char (*p3)[10] = &a;
   char (*p4)[10] = a;
   return 0;
}
這個時候又會有什麼樣的問題?p3+1 和p4+1 的值又是多少?

上述幾個問題,希望讀者能仔細考慮考慮,並且上機測試看看結果。

測試結果:
(1).char (*p2)[5]=a;必須使用強制轉換,如:char (*p2)[5]=(char (*)[5])a;
(2).把陣列大小改變,都會編譯不通過,提示:
error C2440: 'initializing' : cannot convert from 'char (*)[5]' to 'char (*)[3]'
error C2440: 'initializing' : cannot convert from 'char (*)[5]' to 'char (*)[10]'

(3).把以上程式測試程式碼如下:
int main()
{
   char a[5]={'a','b','c','d'};
   char (*p1)[5]= &a;
   char (*p2)[5]=(char (*)[5])a;

   printf("a=%d\n",a);
   printf("a=%c\n",a[0]);
   printf("p1=%c\n",**p1);
   printf("p2=%c\n",**p2);
   printf("p1+1=%c\n",**(p1+1));
   printf("p2+1=%c\n",**(p2+1));

   return 0;
}

輸出:
a=1638208
a=a
p1=a
p2=a
p1+1=?
p2+1=?
Press any key to continue

結論:
根據指標型別及所指物件,表示指標大小,每次加1,表示增加指標型別大小的位元組.----後面還會有解釋說明.