| 聲明 | 含義 | 佔用空間(32位) | 等價直觀形式 |
|---|---|---|---|
int** p; | 指向「一組 int* 指針」的指針 | 4 bytes | int p[x][y]; (x,y 動態) |
int* p[5]; | 5 個 int* 指針組成的數組 | 20 bytes | int p[5][x]; (行固定5,列動態) |
int (*p)[5]; | 指向「5 個 int 的數組」的指針 | 4 bytes | int p[x][5]; (列固定5,行動態) |
int** p:需兩次 malloc(先分配行指針數組,再逐行分配列)。int* p[5]:編譯器已分配 5 指針槽,只需對每個 p[i] 分配列內存。int (*p)[5]:一次性分配連續塊 malloc(sizeof(int)*5*k),p[i] 直接指向第 i 行首址。void MyFun(int x);
void (*FunP)(int) = &MyFun; // 或直接 = MyFun
// 調用等價寫法
(*FunP)(10);
FunP(10); // 編譯器自動解引用
// 作為參數傳遞(回調模式)
typedef void (*Callback)(int);
void CallMyFun(Callback cb, int x) { cb(x); }
CallMyFun(MyFun, 42);
本質:函數名 MyFun 是函數指針常量(地址不可改),FunP 是函數指針變量。類似 int vs int*。
char* copy_str(char* dst, const char* src) {
char* ret = dst;
while ((*dst++ = *src++));
return ret;
}
聲明格式:返回類型 *函數名(參數)。注意優先級:* 結合函數名,非參數。
| 特性 | 數組指針 int (*p)[n] | 指針數組 int* p[n] |
|---|---|---|
| 本質 | 單一指針,指向整個一維數組 | n 個指針組成的數組 |
| 步長 | p+1 跨越 n 個 int | p+1 非法(數組名不可修改) |
| 賦值二維數組 | p = a; (a 為 int a[m][n]) | 需循環 p[i] = a[i]; |
| 訪問元素 | p[i][j] / *(*(p+i)+j) | p[i][j] / *(*(p+i)+j) |
| 內存佔用 | 1 個指針大小 | n 個指針大小 |
無論哪種形式,最終均可用 p[i][j] 訪問元素,編譯器根據類型自動計算偏移:
*(*(p+i)+j):通用指針算術形式(*(p+i))[j]:先解引用得行,再下標int* p[5] 是指針數組;int (*p)[5] 才是數組指針。返回類型 (*名字)(參數),* 必須貼著名字。void f(int a[][5]) 或 void f(int (*a)[5]),列數必須固定。int (*p)[5] = malloc(sizeof(int)*5*rows) 連續內存,釋放只需 free(p)。指針類型系統嚴格對應內存佈局:** 多級間接、*[] 指針容器、(*)[] 整塊數組視圖。理解「類型即內存解釋規則」,配合 sizeof、typedef 輔助推導,即可駕馭所有複雜指針聲明。本文整理自 51CTO 技術博客「C中的幾組指針」。