Like Share Discussion Bookmark Smile

J.J. Huang   2019-10-25   C   瀏覽次數:

C語言 - 第二十一章 | 指標 - 指標的指標

指標的指標(the pointer to the pointer),其作用為「間接參照」,但無論是哪一個名詞,都是令人困惑的,其實指標就是指標,它們的作用單純來說,都是用以儲存記憶體位址。

思考一個問題,要取得int變數的記憶體位址時,會使用int*來宣告指標,要取得double變數的記憶體位址時,會使用 double*來宣告指標,這是因為它們在進行加減法運算時,所位移的單位並不相同,而是根據它們的資料型態而定,而如果只是要儲存一個記憶體位址,你就宣告指標為void*型態。

指標可以用來儲存(某變數的)記憶體位址,所以指標本身就是一個變數,也要佔有記憶體空間才能儲存資訊,那麼指標的記憶體空間位址在哪呢?同樣的使用&運算子就可以得知了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

int main() {

int p = 10;
int *ptr = &p;

printf("p 的值:%d\n", p);
printf("p 的記憶體位置:%p\n", &p);
printf("*ptr 參照的值:%d\n", *ptr);

printf("ptr 儲存的位址值:%p\n", ptr);
printf("ptr 的記憶體位置:%p\n", &ptr);

return 0;
}
1
2
3
4
5
p 的值:10
p 的記憶體位置:0045F808
*ptr 參照的值:10
ptr 儲存的位址值:0045F808
ptr 的記憶體位置:0045F7FC

由以上的範例,你知道ptr在記憶體中的0045F7FC佔據空間,並儲存了0045F808這個值,0045F808也就是p在記憶體中的位置,該位置儲存了10這個值。

如果在上例中,要儲存ptr的記憶體位址,也就是0045F7FC這個值,那麼如何作?

由於ptr是個int*型態變數,如同int變數必須宣告int*指標,所以int*型態變數就必須宣告int**型態的指標。

1
int **ptr2 = &ptr;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>

int main() {

int p = 10;
int *ptr1 = &p;
int **ptr2 = &ptr1;

printf("p 的值:%d\n", p);
printf("p的記憶體位置:%p\n\n", &p);

printf("*ptr1 = %d\n", *ptr1);
printf("ptr1 = %p\n", ptr1);
printf("ptr1 的記憶體位置:%p\n\n", &ptr1);

printf("**ptr2 = %d\n", **ptr2);
printf("*ptr2 = %p\n", *ptr2);
printf("ptr2 = %p\n\n", ptr2);

puts("整理(誰儲存了誰?):");
printf("&p = %p\tprt1 = %p\n", &p, ptr1);
printf("&ptr1 = %p\tprt2 = %p\n", &ptr1, ptr2);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
p 的值:10
p的記憶體位置:0036FC5C

*ptr1 = 10
ptr1 = 0036FC5C
ptr1 的記憶體位置:0036FC50

**ptr2 = 10
*ptr2 = 0036FC5C
ptr2 = 0036FC50

整理(誰儲存了誰?):
&p = 0036FC5C prt1 = 0036FC5C
&ptr1 = 0036FC50 prt2 = 0036FC50

在執行結果中,可以看到最後的整理中,ptr1儲存了p變數佔有的位址,而ptr2則儲存了ptr1佔有的位址,所以使用*取值運算子時,*ptr2取出的是ptr1儲存的值,也就是&p,而再使用一次*運算子時,也就是**ptr2時,因為*ptr2 == ptr1,所以 *(*ptr2 ) == *ptr1,而*ptr1 == p,所以也就是取出了p的值了。


註:以上參考了
指標的指標