指針是 C 語言的靈魂,也是區分「會用 C」與「精通 C」的分水嶺。本文從計算機存儲模型出發,建立指針與地址的本質認知,系統講解指針變量定義語法、初始化規則、賦值約束、取址/取內容運算符,並揭示空指針與動態分配的關鍵細節。
int x; → &x 類型是 **「指向 int 的指針」**,值是 x 的地址。double d; → &d 類型是 **「指向 double 的指針」**,值是 d 的地址。類型標識符 *變量名; /* * 屬於聲明符一部分,非乘法 */
int *ip;:ip 為指向 int 的指針變量,專存 int 變量地址。static int *p2;:指向靜態 int 的指針。float *p3; char *p4;:分別指向 float、char。鐵律:一個指針變量**只能指向同一類型**對象(除 void* 通用指針外)。
int i, *ip = &i; /* 合法:用 &i 初始化 ip */
/* 錯誤:int *ip = i; (無 & 符) */
/* 錯誤:int *ip = *&i; (解引用結果是 int 值) */
int i, *ip;
ip = &i; /* 正確 */
ip = 1000; /* 錯誤:整數不可直接賦予指針 */
*ip = &i; /* 錯誤:左值是 int,非指針 */
malloc 失敗返回 NULL)。區域指針未初始化為**隨機地址**(垃圾值),直接使用極其危險。正確做法:
#include /* 或 舊版 */
int *ip = (int*)malloc(sizeof(int)); // 分配 1 個 int
*ip = 420; // 解引用賦值
char *str = (char*)malloc(20); // 分配 20 字節
strcpy(str, "Good, Answer!"); // 字符串拷貝
/* 分配陣列 */
int *arr = (int*)malloc(3 * sizeof(int));
arr[0] = 1234; *(arr+1) = 4567; *(arr+2) = 234; // 下標/指針算術等價
關鍵理解:malloc 返回 void*,需**強制轉換**為目標指針類型(C++ 必須,C 隱式轉換但建議顯式)。分配後的記憶體**專屬於該指針管理**,用完必須 free 歸還。
&&a 類型為「指向 a 類型的指針」。scanf、指針初始化中大量使用。** 是類型修飾符(標識「這是指針」);表達式中的 * 是運算符(標識「取所指值」)。main() {
int a = 5, *p = &a;
printf("%d", *p); // 輸出 5:*p 等價於 a
}
p = &a; p = q; p = NULL;p + n、p - n、p++、p--(按元素縮放)。== != < > <= >=(同一數組/塊內)。p - q 得元素個數 (ptrdiff_t)。| 誤區代碼 | 問題 | 正確寫法 |
|---|---|---|
int *p; *p = 10; | 野指針解引用 → 崩潰 | int *p = malloc(...); *p = 10; |
int *p = 1000; | 整數賦指針 | int *p = (int*)1000; (極少見,硬體編程) |
void f(int *p) { p = malloc(4); } | 形參修改不影響實參 | void f(int **p) { *p = malloc(4); } |
free(p); *p = 0; | 釋放後使用 (UAF) | free(p); p = NULL; |
指針 = **帶類型的地址變量**。掌握「定義語法、&/* 對偶、初始化/賦值約束、動態分配配合、受限運算集」五大支柱,即打通了 C 語言操作記憶體的任督二脈。後續將深入指針與數組、字符串、函數、結構的深度結合,敬請期待。