指標是 C 語言的靈魂,亦是初學者最大的挑戰。本文從記憶體位址概念切入,系統講解指標變數定義、間接存取、函數傳址呼叫、指標與陣列/字串關係、常見錯誤與練習,並補充邏輯/線性/物理位址轉換背景知識,助你建立扎實的指標心智模型。
位址是系統 RAM 中特定位置的編碼,通常以十六進位表示(如 `0x7fff5fbff81c`)。程式透過位址定位資料。在 80386 保護模式下,分為:

int a = 10;
int *p = &a; /* p 儲存 a 的位址 */
*p = 20; /* 透過 p 修改 a 的值,a 變為 20 */
printf("%p\n", p); /* 印出位址 */
printf("%d\n", *p); /* 印出 20 */
int *p; 中的 `*` 僅為宣告標記,非解參考運算。void change(int *n) { *n = 20; }
int a = 10;
change(&a); /* a 變為 20 */
陣列名在運算式中(除 `sizeof`、`&` 外)退化為首元素位址。
int ages[5] = {10, 11, 19, 78, 67};
int *p = ages; /* 等價於 &ages[0] */
printf("%d\n", p[2]); /* 19 */
printf("%d\n", *(p+2)); /* 19,指標算術:p+2 位址增加 2*sizeof(int) */
void change(int *array) { /* 或 int array[] */
printf("%d\n", array[2]);
}
change(ages); /* 實際傳遞首元素位址 */
注意:函數內 `sizeof(array)` 回傳指標大小(8 bytes on 64-bit),非陣列總大小。
指標 `+1` 實際位址增加量 = `sizeof(指標指向類型)`。
| 方式 | 範例 | 儲存區 | 可修改內容 | 適用場合 |
|---|---|---|---|---|
| 字元陣列 | `char name[] = "itcast";` | 堆疊 | 是 | 需頻繁修改字串 |
| 字元指標 | `char *name = "itcast";` | 常數區(唯讀) | 否(嘗試修改導致崩潰) | 唯讀、高頻使用字串 |
char name[] = "it"; name[0] = 'T'; /* OK */
char *name2 = "it"; *name2 = 'T'; /* Crash! */
char *name3 = "it"; printf("%p %p\n", name2, name3); /* 可能相同,編譯器優化合併常數 */
/* 指標陣列 */
char *names[5] = {"jack", "rose", "jake"};
/* 二維字元陣列 */
char names2[2][10] = {"jack", "rose"};
int *p, p1; /* p 是指標,p1 是 int,非雙指標 */
int *p, *p1; /* 正確:兩個指標 */
/* 錯誤:僅交換區域指標指向 */
void swap_wrong(int *v1, int *v2) { int *t = v1; v1 = v2; v2 = t; }
/* 正確:交換指向的值 */
void swap_correct(int *v1, int *v2) { int t = *v1; *v1 = *v2; *v2 = t; }
char c = 1; /* 0000 0001 */
char *p = &c;
printf("%d\n", *p); /* 1 */
void test() {
char *cp; int *ap; long *bp;
printf("%zu %zu %zu\n", sizeof(cp), sizeof(ap), sizeof(bp)); /* 64-bit 皆為 8 */
}
指標本質是位址,核心操作是 `&`(取址)與 `*`(解參考)。掌握指標與陣列/字串的關係、指標算術規則、const 修飾位置(`const int *` vs `int * const`)、以及避免野指標與類型不匹配,即可駕馭 C 語言最強大也最危險的特性。