1.指針數組和數組指針的概念
指針數組:指針數組是一個數組,是指由指針構成的數組,在這個數組中的所有元素都是指針,每個指針佔用相同的字節。
數組指針:數組指針是一個指針,是指一個數組的指針,數組兩字表示這個指針指向一個數組的首地址,並且這個指針加1時移動的位置是整個數組的長度。
2.指針數組
一個可行的指針數組定義如下:
char *arr[4] = {"hello", "world", "xiang", "qian"};
這裏的寫法是*arr[4],則表示指針數組,如果是(*arr)[4],則表示數組指針。上面的代碼中arr是一個有4個元素的數組,每個元素都是指針,因此arr佔據的空間是14個字節,而後面的字符串呢?他們被分配在另一個內存區域,由arr指向他們,因此可以試着向字符串中多寫入幾個字母,再用sizeof(arr)輸出觀察,結果依然是16個字節。所以指針數組,相當於是把好幾個指針放在了一個數組裏,僅此而已。
3.指向數組的指針
對於一維數組,實際上數組的名字就是數組的首地址,數組的名字也可以當做指針使用。假設一個數組arr[5]存放了5個整型數字,在定義一個指針int *p = arr;那麼arr[2]和p[2]的值是一樣的。
而如果定義了一個數組指針指向了一個一維數組呢?如int (*p1)[5] = arr這時候相當於是一個指針,注意是一個!一個指針指向了一塊內存區域,這塊區域是個一維數組的首地址,而對這個指針進行加一操作的時候,這個指針實際上移動了整個數組長度的距離。這個可以類比來理解,指針之所以需要聲明類型,是爲了說明清楚指針它指向什麼類型的數據,這樣加一操作是才能知道移動多少距離,指向char的指針加一時移動1個字節,指向double的指針加一時移動8個字節。同樣的道理,指向數組的數組指針如果寫成int[5] (*p1)這樣會比較好理解,這就告訴我們p1這個指針加一時一次要移動5個int的距離。實際中不能這麼寫,這只是爲了好理解。
對於一維數組的訪問,使用普通指針就夠了,如果使用數組指針反而會比較麻煩。
#include <iostream>
using namespace std;
int main() {
int arr1[5] = {1, 2, 3, 4, 5};
int *p1;
int (*p2)[5] = &arr1;
//p1 = &arr1[0];
p1 = arr1;
cout << sizeof(arr1) << endl;
cout << &arr1 << '\t' << p1 << endl;
cout << &arr1 + 1 << '\t' << p1 + 1 << endl;
cout << endl;
cout << &arr1 << '\t' << p2 << endl;
cout << &arr1 + 1 << '\t' << p2 + 1 << endl;
cout << p1[2] << '\t' << *(*(p2+0)+2)<< endl; }
代碼輸出爲:
20
0x28fef4 0x28fef4
0x28ff08 0x28fef8
0x28fef4 0x28fef4
0x28ff08 0x28ff08
3 3
對於二維數組的訪問,也可以使用普通指針或者數組指針。假設一個數組arr2[3][3],定義一個普通指針獲取arr2[0][0]的地址後,就可以操作其所有的元素,本質上這個數組在內存中的位置是連續的,因此我們當然知道對指針增加幾個單位後會指向哪個位置。而使用數組指針時,int (*p2)[3] = arr2;一定要記住p2後面的方括號裏的數字要和數組的列數相同,因爲這樣對這個指針進行加一操作時,移動的單位就是數組的列數,相當於移動了一整行的距離。
#include <iostream>
using namespace std;
int main() {
int arr2[3][3] = {{1, 2, 3},
{4, 5, 6},
{7, 8, 9}};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++)
cout << arr2[i][j] << ' ';
cout << endl;
}
int *p3 = &arr2[0][0];
cout << p3[0] << ' ' << p3[7] << endl;
int (*p4)[3] = arr2;
cout << arr2 << '\t' << p4 << endl;
cout << arr2 + 1 << '\t' << p4 + 1 << endl;
cout << 0x28fee8 - 0x28fedc << endl;
cout << *(*(p4+0)+1) << '\t' << *(*(p4+2)+0) << endl;
return 0;
}
輸出爲:
1 2 3
4 5 6
7 8 9
1 8
0x28fedc 0x28fedc
0x28fee8 0x28fee8
12
2 7