指標,用來儲存變數的記憶體位址,宣告方式如下:
資料型別 *變數名稱 or 資料型別* 變數名稱
假設今天有一個整數變數x
,內容為38
,那我們如何利用指標接收變數x
的記憶體位址呢? 方法如下:
int *p = &x;
現在指標(64位元電腦下通常為8bytes
)和變數在記憶體中的樣子如下圖所示:
0x7ffd8d3f7f46 - 0x7ffd8d3f7f52
接著我們試著用指標輸出內容: 以下示範:
#include<stdio.h>
int main()
{
int *p, x=38;
p = &x;
printf("%p",p); //輸出變數x的記憶體位址,以16進制表示
return 0;
}
接著我們想要利用指標輸出變數x
的內容,如何實現? 方法如下:
#include<stdio.h>
int main()
{
int *p, x=38;
p = &x;
printf("%d",*p); //輸出變數x的內容
return 0;
}
上面程式碼中,我們藉由在p
前面添加*
(我們稱這樣為解參考)。
好,今天我又想宣告一個指標儲存p
的記憶體位址,如何實現? 方法如下:
#include<stdio.h>
int main()
{
int *p, x=38;
p = &x;
int **ptr = &p;
printf("%p\n",p); //輸出變數x的記憶體位址,以16進制表示
printf("%p\n",ptr); //輸出p的記憶體位址,以16進制表示
printf("%p\n",*ptr); //輸出變數x的記憶體位址,以16進制表示
printf("%d",**ptr); //輸出變數x的內容
return 0;
}
#include <stdio.h>
int main() {
int test[5]={60,70,80,90,100};
printf("%p\n",&test[0]);
printf("%p",test);
return 0;
}
/* 輸出
0x7ffffdcab4f0
0x7ffffdcab4f0
*/
test
和&a[0]
的輸出相同,表示了test
其實也可以做為一個指標(隱式轉換),指向a[0]
的記憶體位址。接著我們再做一些變化並測試:
#include <stdio.h>
int main() {
int test[5]={60,70,80,90,100};
printf("%p\n",&test[0]+1);
printf("%p",test+1);
return 0;
}
/* 輸出
0x7ffffdcab4f4
0x7ffffdcab4f4
*/
test+1
(等同&test[0]+1
)時,輸出的記憶體位址增加了4,其實不難理解,意思就是他指向了一維陣列下一個儲存空間的記憶體位址,即a[1]
的記憶體位址。我們一樣可以透過解參考輸出陣列內容。如下示範:#include <stdio.h>
int main() {
int test[5]={60,70,80,90,100};
printf("%d\n",*test);
printf("%d",*(test+1));
//printf("%d",*test+1); 這樣寫會變為60+1等於61
return 0;
}
/* 輸出
60
70
*/
好,現在如果我想要再宣告一個指標指向這個陣列,只要把名字test
丟給指標就行,如下示範:
#include <stdio.h>
int main() {
int a[5]={60,70,80,90,100};
int *p = a;
printf("%p\n",a);
printf("%d\n",*a);
printf("%p\n",a+1);
printf("%d\n",*(a+1));
printf("%p\n",p);
printf("%d\n",*p);
printf("%p\n",p+1);
printf("%d\n",*(p+1));
printf("%p\n",&p[0]);
printf("%d\n",p[0]);
printf("%p\n",&p[1]);
printf("%d\n",p[1]);
return 0;
}
/* 輸出
0x7fffb32eb0e0
60
0x7fffb32eb0e4
70
0x7fffb32eb0e0
60
0x7fffb32eb0e4
70
0x7fffb32eb0e0
60
0x7fffb32eb0e4
70
*/
p
也可以使用索引的方式存取陣列,使用上就像是a
。接著,我還有一些觀念想講:
&
)時,情況有所不同。a
: 在表達式中,a
會被視為指向陣列第一個元素的指標,型別為 int*
(假設 a
是 int
型別的陣列)。&a
: 這裡,&a
取得的是整個陣列 a
的位址,其型別為 int (*)[N]
,其中 N
是陣列的大小。int*
: 指向 int
型別的指標。int (*)[N]
: 指向大小為 N
的 int
陣列的指標。指標算術中的位址計算取決於指標的型別和指標運算。當對指標進行加法(如 ptr + 1
)時,實際的位址增加量為 1 * sizeof(指標所指向的型別)
。
int*
: ptr + 1
將位址增加 1 * sizeof(int)
。int (*)[N]
: ptr + 1
將位址增加 1 * sizeof(int[N])
,也就是 N * sizeof(int)
。假設我們有一個陣列:
int a[4] = {1, 2, 3, 4};
&a
的型別: int (*)[4]
,即指向包含 4 個整數的陣列的指標。&a + 1
: 由於 &a
的型別是 int (*)[4]
,因此加1時,實際增加的位址為 1 * sizeof(int[4])
,也就是 1 * (4 * sizeof(int))
。示例 1:使用 &a
(指向整個陣列的指標)
int a[4] = {1, 2, 3, 4};
int (*p)[4] = &a; // p 的型別是 int (*)[4]
printf("%p\n", p); // 輸出陣列 a[0] 的位址
printf("%p\n", p + 1); // 輸出位址增加 4 * sizeof(int) 後的位址
p + 1
將位址增加 4 * sizeof(int)
。示例 2:使用 a
(指向第一個元素的指標)
c
int a[4] = {1, 2, 3, 4};
int *p = a; // p 的型別是 int*
printf("%p\n", p); // 輸出 a[0] 的位址
printf("%p\n", p + 1); // 輸出位址增加 sizeof(int) 後的位址
p + 1
將位址增加 sizeof(int)
。