這篇文章主要用來記錄學習指標基本的宣告規則以及雙重指標、三重指標…等多重指標之間的存取關係
先從最基本的指標觀念說起
- * (米字號)的功能為:宣告指標變數用、取值運算子(取出該變數所存放的值)。
- & 的功能為:取"址"運算子 (取某變數的記憶體位置)
指標的功能是用來存放某個資料型態的記憶體位置,舉個簡單的例子
int p = 10; /宣告一個存放整數10的整數變數P
int *ptr = &p /宣告整數指標變數ptr存放另一個整數變數的記憶體位置&p
↑ 宣告指標變數時需要在變數名稱的前面加入* (米字號,在這裡用作宣告指標)
宣告的方是可以 int* ptr / int * ptr / int *ptr 三種格式
*只要是在資料型態跟變數名稱之間即可,且可以一次宣告多告指標變數 int *ptr,*ptr2
但是建議使用將指標放在變數旁邊的方式宣告 int *ptr
因為怕造成日後使用上的誤會,例如:
版本一:
int *ptr,ptr2; /ptr為整數指標變數,ptr2為整數變數
版本二:
int *ptr,*ptr2; /ptr,ptr2皆為整數指標變數
另外,若只需要單純宣告一個指標記錄非特定資料型態的記憶體位置,則可以使用以下方式宣告指標變數
void *ptr;
而*(米字號)在宣告的變數的時候是用作宣告指標變數,而在一般情況下(非宣告、非數學乘法時),則為取值運算子,以下例子解釋:
int p = 10;
int *ptr = &p; /這裡的*米字號用作宣告指標變數
cout << *ptr; /這裡會輸出10,這裡的*米字號就是用作取值運算子
cout << ptr; /這裡會輸出ptr所存放的記憶體位置(p的記憶體位置) 也就是&p
以上是宣告指標的部分。
再來是雙重指標(指標的指標)
指標的指標,說穿了就是在宣告一個指標變數記錄另一個指標的位置,宣告的方式如下:
int p = 10;
int *ptr = &p; /使用指標ptr記錄p的記憶體位置
int **ptr = &ptr; /使用雙重指標記錄指標ptr的記憶體位置
宣告的方式這裡可以思考成,
一開始我們宣告整數變數時是只使用 int p 宣告指標變數時,
因為多了個指標的型態,所以便成為 int *ptr
之後我們要宣告的雙重指標(指標的指標),也就是說指標的型態為 *ptr,
那麼指標的指標就等於*(*ptr) —>這邊方便理解所以使用括號
由此往下推,三重指標就等於(***ptr),由於是存放指標的指標,所以可以想成*(**ptr),
為了方便方便釐清指標所存放的東西,這邊用以下(三重指標)例子說明:
int main() {
int p =10;
int *ptr1 = &p; /指標變數ptr存放p的記憶體位置&p
int **ptr2 = &ptr; /指標的指標變數存放ptr的記憶體位置&ptr
int ***ptr3 = &ptr2; /指標的指標的指標變數存放ptr2的記憶體位置&ptr2
cout << "p的值:" << p << endl;
cout << "p的記憶體位置: " << &p << endl;
cout << endl;
cout << "ptr1 = " << ptr1 << endl;
cout << "*ptr1 = " << *ptr1 << endl;
cout << "ptr1的記憶體位置: " << &ptr1 << endl;
cout << endl;
cout << "**ptr2 = " << **ptr2 << endl;
cout << "*ptr2 = " << *ptr2 << endl;
cout << "ptr2 = " << ptr2 << endl;
cout << "ptr2的記憶體位置" << &ptr2 << endl;
cout << endl;
cout << "***ptr3 = " << ***ptr3 << endl;
cout << "**ptr3 = " << **ptr3 << endl;
cout << "*ptr3= " << *ptr3 << endl;
cout << "ptr3= " << ptr3 << endl;
cout << "ptr3的記憶體位置" << &ptr3 << endl;
}
輸出結果如下:
這邊依序解釋,可以看出來:
-
ptr1(存放p的記憶體位置) → ptr1 = &p
-
*ptr1(取出ptr1指標變數所存放的記憶體位置的值) → *ptr1 = 10
-
ptr2(存放指標ptr1的記憶體位置) → ptr2 = &ptr1
-
*ptr2(可以思考成從ptr2取值,而從上面得知ptr2存放的是指標ptr1的記憶體位置,
所以就是從ptr1的記憶體位置取值) → *ptr2 = *(&ptr1) = ptr1 = &p ,當*&這兩個符號放在一起可以抵銷 -
**ptr2(思考成*(*ptr2),從*ptr2的位置取值,也就是說從&p的位置取值) → **ptr2 = *ptr1 = 10
-
ptr3(存放ptr2雙重指標的記憶體位置) → ptr3 = &ptr2
-
*ptr3(從ptr3取值,由上可知ptr3存放ptr2的記憶體位址,也就是說從&ptr2取他存放的值)
→ *ptr3 = *(&ptr2) = ptr2 = &ptr1 -
**ptr3(可看成*(*ptr3),也就是從*ptr3取值) → **ptr3 = *(*ptr3) = *(&ptr1) = ptr1
-
***ptr3(一樣看成*(**ptr3),等於從**ptr3取值) → ***ptr3 = *(**ptr3) = *ptr1 = 10
以上,藉由這些規則可以一步步推演往後更多的四重指標、五重指標...多重指標。
有任何錯誤或問題在麻煩大家提出更正。