指針是 C 語言最強大也最危險的特性。本文系統梳理指針聲明、初始化、使用、解引用、邊界檢查等環節的典型錯誤,並給出經過驗證的防範模式,助力寫出健壯、安全的 C 代碼。
int* ptr1, ptr2; // 錯誤:ptr1 是指針,ptr2 是 int
int* ptr1, *ptr2; // 正確
建議:使用 typedef 而非宏定義:
typedef int* PINT;
PINT ptr1, ptr2; // 兩者皆為指針,編譯器可檢查作用域
int *p;
printf("%d\n", *p); // 未定義行為,p 含隨機地址
鐵律:聲明即初始化為 NULL。
int *pi = NULL;
// 使用前檢查
if (pi != NULL) { /* 安全使用 */ }
assert(pi != NULL); // 調試階段斷言
float *vec = malloc(20 * sizeof(float));
if (vec == NULL) { /* 處理 OOM */ }
gets、strcpy、strcat 等不安全函數;sizeof 誤用:sizeof(ptr) 返回指針大小而非數組長度。char first[8] = "1234567";
char middle[8] = "1234567";
char last[8] = "1234567";
middle[-2] = 'X'; // 寫入 first 尾部
middle[10] = 'X'; // 寫入 last 頭部
輸出顯示 first 和 last 被篡改。對策:傳遞數組長度、使用 strncpy/snprintf、編譯器開啟 -fstack-protector、運行時工具 (Valgrind/ASan)。
int buffer[20];
int *p = buffer;
for (int i = 0; i < sizeof(buffer)/sizeof(int); ++i) // 正確
p[i] = 0;
free(ptr); ptr = NULL;C 無原生有界指針,可手動實現邊界檢查宏/函數:
#define SIZE 32
char name[SIZE];
char *p = name;
if (p >= name && p < name + SIZE) { /* 有效 */ }
或使用編譯器插桩工具(如 CBMC、Frama-C)進行靜態邊界分析。
指針統一大小(32位 4 字節),作為函數參數傳遞大結構體高效;但靈活性換來的是開發者需自負內存安全責任。現代 C++ 推薦優先使用引用、智能指針、容器、span 等安全抽象,僅在底層交互層使用裸指針。
指針誤用是 C 程序安全漏洞的第一大來源。嚴守「聲明即初始化、邊界必檢查、釋放即置空、所有權明確」四大鐵律,配合編譯器警告、靜態分析、動態檢測工具鏈,可將風險降至最低。