指標的指標


記憶體位址就單純是個值,若只是單純想儲存記憶體位址,使用 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;