指針是 C 語言的核心靈魂,也是初學者最大的攔路虎。本文系統梳理指針概念、聲明、使用、動態記憶體管理、多級指針等核心知識,並附帶完整可執行範例代碼。
指針本質上是一個儲存記憶體地址的變數。 它「指向」另一個變數所在的記憶體位置,透過地址間接存取資料。

// 語法:資料型別 *指針名 = &目標變數; int a = 10; int *p = &a; // p 指向 a 的地址
關鍵規則:
&a、malloc 返回值、另一指針),不能是資料值| 運算子 | 含義 | 範例 |
|---|---|---|
* | 解引用(取值) | *p 獲取 p 指向的值 |
& | 取址 | &a 獲取 a 的地址 |
* (聲明時) | 標識指針型別 | int *p |
* (運算時) | 單目運算子/乘法 | *p / 5 * 5 |
#include <stdio.h>
int main(void) {
int a = 10;
int *p = &a; // 聲明並初始化
printf("a 的值為 %d\n", a); // 10
printf("a 的值為 %d\n", *p); // 10(透過指針取值)
printf("a 的地址為 %p\n", (void*)p); // 地址值
printf("a 的地址為 %p\n", (void*)&a); // 相同地址
*p = 20; // 透過指針修改 a
printf("修改後 a = %d\n", a); // 20
return 0;
}
空指針 (NULL):明確表示「不指向任何有效記憶體」,防止野指針。
int *p = NULL; // 安全的初始狀態
動態記憶體分配:
#include <stdlib.h> // malloc, free
int *p = (int*)malloc(sizeof(int)); // 分配 4 位元組
if (p == NULL) {
fprintf(stderr, "記憶體分配失敗\n");
exit(EXIT_FAILURE);
}
*p = 100;
printf("值:%d\n", *p);
free(p); // 必須釋放,避免記憶體洩漏
p = NULL; // 防止懸空指針
鐵律:malloc 與 free 必須成對出現。
int a = 1;
int *p1 = &a; // 一級指針
int **p2 = &p1; // 二級指針,指向 p1
printf("%d\n", **p2); // 1:p2 → p1 → a
應用場景:函數修改指針本身、二維動態陣列、命令列參數 char **argv。
| 陷阱 | 後果 | 防範 |
|---|---|---|
| 野指針 | 程式崩潰/資料損壞 | 聲明即初始化,free 後置 NULL |
| 記憶體洩漏 | 記憶體耗盡 | malloc/free 成對,工具檢測 |
| 懸空指針 | 存取已釋放記憶體 | free 後立即置 NULL |
| 緩衝區溢出 | 覆蓋相鄰記憶體 | 嚴格檢查邊界,使用安全函數 |
| 型別不匹配 | 解讀錯誤 | 指針型別與目標型別一致 |
歷史原因導致不同編譯器 int 大小不同:
int = 2 位元組int = 4 位元組int 通常仍為 4 位元組,long/指針為 8 位元組最佳實踐:使用 sizeof(int)、int32_t (需 <stdint.h>) 等可移植寫法,避免硬編碼大小。

指針賦予 C 語言直接操作記憶體的威力,也帶來了相應的責任。掌握指針的關鍵在於:理解記憶體模型、嚴格遵循初始化/釋放規範、善用工具檢測(Valgrind、AddressSanitizer)。從基礎操作到動態管理、多級指針,層層遞進,方能駕馭 C 語言的核心力量。