記憶體位址就單純是個值,若只是單純想儲存記憶體位址,使用 void*
型態的指標就可以了。
如果需要對指標作運算,那指標需要型態,在〈指標與陣列〉最後就看到了,同一個位址,因為指標型態的不同,遞增等運算的結果就不同。
那麼什麼是指標的指標?…呃…還是指標!指標就是儲存記憶體位址,差別在於指標的型態,來看看底下的範例好了:
#include <iostream>
using namespace std;
int main() {
int n = 10;
int *p1 = &n;
int **p2 = &p1;
cout << "n 位址:" << p1 << endl
<< "p1 位址:" << p2 << endl;
return 0;
}
執行結果:
n 位址:0x61feb8
p1 位址:0x61feb4
n
儲存了 10,n
的位址 0x61feb8,指定給 p1
儲存,而 p1
的位址是 0x61feb4
,指定給 p2
儲存。
n
的型態是 int
,&n
取得的值型態是 int*
,因此指定 int*
型態的 p1
,因為指標的宣告是 type *variable
嘛!p1
的 type 是 int*
,自然地,能儲存 &p1
值的變數,就是宣告為 int* *p
,只不過習慣上,宣告時會將 **
排在一起,也才會有方才 int **p2 = &p1
的寫法,若要說 p2
的型態則是 int**
。
這個簡單的範例,只是用來理解想用指標儲存另一指標的位址時,型態上是怎麼宣告罷了,單純只是用指標來儲存另一個指標的位址,沒有太大的意義,重點在於指標的型態在運算時扮演的作用,例如〈指標與陣列〉中,對變數取址後遞增 1,目的是為了要位移一整個陣列空間:
constexpr int LENGTH = 5;
int arr[LENGTH] = {10, 20, 30, 40, 50};
int len = *(&arr + 1) - arr;
一維陣列變數的元素位址可以儲至 int*
指標,那二維陣列呢?在〈二維(多維)陣列〉談過,多維陣列是由陣列的陣列構成,二維陣列可以看成數段一維陣列構成,必須宣告每段一維陣列的長度為何:
int arr[2][3] = {{10, 20, 30}, {40, 50, 60}};
int (*p)[3] = arr;
三維陣列可以看成數段三維陣列構成,因此必須宣告每段二維陣列的維度為何,例如:
int arr[1][2][3] = {{{10, 20, 30}, {40, 50, 60}}};
int (*p)[2][3] = arr;
這種語法還蠻麻煩的,如果知道指標的型態在運算上會有什麼作用,然而想專心於計算,不想理會型態宣告的語法,使用 auto
是比較方便:
int arr1[2][3] = {{10, 20, 30}, {40, 50, 60}};
auto p1 = arr1;
int arr2[1][2][3] = {{{10, 20, 30}, {40, 50, 60}}};
auto p2 = arr2;