指標操作是 C 語言分水嶺。本文聚焦實戰高頻坑點:野指標三大來源、空指標判斷跨平台差異、void* 五大使用規則,附代碼反模式與正確模式對照。
char* p; strcpy(p, "x"); → 垃圾位址
char* p = NULL; 或 char* p = malloc(100);char* p = malloc(100);
strcpy(p, "hello");
free(p); // 記憶體還給堆,p 仍指向原位址
if (p != NULL) // 真!但指向垃圾
strcpy(p, "world"); // 崩潰/靜默破壞
free(p); p = NULL;void Test() {
A* p;
{ A a; p = &a; } // a 生命週期結束
p->Func(); // p 成野指標
}
NULL 定義:C 多為 (void*)0,C++ 為 0(C++11 推薦 nullptr)NULL 非 0(如 0xDEADBEEF)if (p == NULL) / if (NULL == p) —— 明確、跨平台安全if (!p) —— 依賴隱性轉 bool,C++ 推薦,C 需確認 NULL 定義if (p == 0) —— 平台相依風險Item* pItem = itemList.getItem(index); // 可能回傳 NULL
if (pItem == NULL) return ERROR; // 必須檢查
pItem->doSomething(); // 安全
| 規則 | 說明 | 正確範例 | 錯誤範例 |
|---|---|---|---|
| 1. 函數無回傳值 → void | 強制語意明確 | void init(); | init() { return 1; } (隱性 int) |
| 2. 函數無參數 → void | C++ 強制,C 允許傳參 | int func(void); | func(2); (C++ 編譯錯) |
| 3. 謹慎用 void* 運算 | ANSI 禁止 ++,GNU 允許 | (char*)pvoid++; | pvoid++; |
| 4. 參數可為任意型別 → void* | 記憶體操作、泛型介面 | memcpy(void*, void*, size_t) | memcpy(char*, char*, size_t) |
| 5. void 不能定義變數 | 抽象型別,無實例 | — | void a; (編譯錯) |
static_cast