指標的指標,說穿了只是雙重指標而已。假設 ptr1 是指向變數a的指標,ptr2為指向ptr1的指標,那麼 ptr2 就是變數a “指標的指標”(ptr2→ptr1→a)。這部份很容易搞亂,麻煩請準備紙筆在手邊會比較方便。
現在考慮以下指令:
int a = 10;
int *ptr1 = &a;
如果要對 a 變數多設一層指標,可以這麼做:
int **ptr2 = &ptr1;
或者是分二行寫:
int **ptr2=NULL;
int ptr2 = &ptr1;
請注意,這裡沒辦法寫成 int **ptr2 = &(&a); 在使用二次指標時,一定要先使用一次指標才行。同樣的,使用三次指標,一定要先使用過二次指標。範例如下:
int a = 10;
int *ptr1 = &a;
int **ptr2 = &ptr1;
int ***ptr3 = &ptr2;
記憶體示意圖如下所示:
儲存值 |
12FF54 |
… |
12FF60 |
… |
10 |
… |
記憶體位址 |
12FF48 |
… |
12FF54 |
… |
12FF60 |
… |
變數名稱 |
Ptr2 |
|
Ptr1 |
|
A |
|
儲存值 來源根據 |
Ptr1 位址 |
|
變數A 位址 |
|
初值 設10 |
|
1. 為什麼不能寫成 int **ptr2 = &(&a);
請記得 & 運算子的實際功能,是在”取得該變數的位置”,既然&a已經是取出變數a的位址了,那試問 &(&a) 又是要取誰的位址?
2. printf(“%0X\n”, **ptr2); 顯示會是什麼?
(2.1) *ptr2:我們先想一下,*ptr2會是什麼東西。由於我們有指定 ptr2 = &ptr1,所以ptr2的內容值就是ptr1的位址值,以圖表例而言,就是12FF54,接著*ptr2會跑去 12FF54抓其內容,所以 *ptr2 = 12FF60
(2.2) **ptr2:接著我們把**ptr2看成*(*ptr2),從上面我們已經知道*ptr2 = 12FF60,接著 *(*ptr2)就是跑到12FF60再抓一次值,其內容就是10(也就是變數a的內容)
3. 如何知道變數 a 的內容值
a的內容值 = ptr1(依址取值) = ptr2(依址取值 再依址取值),
a = *ptr1 = **ptr2;
4. 如何知道 ptr1 的內容值
ptr1 內容值 = 變數a位址值 = ptr2(依址取值)
ptr1 = &a = *ptr2
5. 如何知道 ptr2 的內容值
ptr2 內容值 = ptr1 位址值
ptr2 = &ptr1
如果以上覺得有點混亂,希望以下的程式碼會有所幫助。如果有問題,歡迎回覆留言。
6. 程式碼
// ====================================
// FileName: Ptr2Ptr.cpp
// Author : Edison.Shih.
// Complier: VC 2008
#include <stdio.h>
// ====================================
//
int main(int argc, char **argv)
{
int a= 0x10;
int *ptr1 = &a;
int **ptr2 = &ptr1;
// int **ptr2 = &(&ptr1); // complier error
printf("a= %06X ptr1 =%06X ptr2=%06X\n", a, ptr1, ptr2);
printf("&a=%06X &ptr1=%06X &ptr2=%06X\n", &a, &ptr1, &ptr2);
// printf("*a=%0X\n", *a); // complier error
printf("xxxxxxxxx *ptr1=%06X *ptr2=%06X\n",*ptr1, *ptr2);
// get a's value
printf("========= get a's value =========\n");
printf("a = %06X\n", a);
printf("*ptr1 = %06X\n", *ptr1);
printf("**ptr2 = %06X\n", **ptr2);
// get a's address, = ptr1's value
// &a = ptr1 = *ptr2
printf("========= get a's address =========\n");
printf(" &a = %06X\n", &a);
printf("ptr1 = %06X\n", ptr1);
printf("*ptr2 = %06X\n", *ptr2);
// get ptr1's address
// &ptr1 = ptrw
printf("========= get ptr1's address =========\n");
printf("&ptr1 = %06X\n", &ptr1);
printf(" ptr2 = %06X\n", ptr2);
return 0;
}
7. 執行結果
a= 000010 ptr1 =12FF60 ptr2=12FF54
&a=12FF60 &ptr1=12FF54 &ptr2=12FF48
xxxxxxxxx *ptr1=000010 *ptr2=12FF60
========= get a's value =========
a = 000010
*ptr1 = 000010
**ptr2 = 000010
========= get a's address =========
&a = 12FF60
ptr1 = 12FF60
*ptr2 = 12FF60
========= get ptr1's address =========
&ptr1 = 12FF54
ptr2 = 12FF54