[cpp]
int i = 10;
int *p; // 宣告指向 int 的指針
p = &i; // 取址賦值
printf("%d\n", *p); // 解引用獲取值 10
核心概念:指針本身是一個變量,佔用固定大小內存(32位 4B,64位 8B),存儲另一塊內存的地址。*p 訪問該地址處的數據。
[] 說明是數組,() 說明是函數。* 說明是指針,const/類型說明指向類型。[cpp]
char (*a)[100]; // ① 指向「含 100 個 char 的數組」的指針
char *a[100]; // ② 含 100 個「char*」的數組(指針數組)
讀法演示:
a → 右邊 [100] → 是數組?不,右邊是 ),再看左邊 * → 是指針 → 指向 char [100]。a → 右邊 [100] → 是含 100 元素的數組 → 元素類型看左邊 char* → 指針數組。[cpp]
int arr[10][100];
int *p = &arr[0][0]; // 指向 int
int (*q)[100] = &arr[0]; // 指向 int[100]
printf("%zu\n", sizeof(*p)); // 4 (sizeof(int))
printf("%zu\n", sizeof(*q)); // 400 (sizeof(int[100]))
p++; // 地址 +4
q++; // 地址 +400 (跳過整整一行)
圖解:
[cpp]
char *str[2] = {"liushuai", "kobe"}; // 指針數組,每項指向字面量
printf("%s %s\n", str[0], str[1]); // 輸出: liushuai kobe
[cpp]
int *foo(int); // 返回 int* 的函數
void (*bar)(); // 指向「無參無返回值函數」的指針
[cpp]
// 返回「接受 double*, char 並返回 int 的函數指針」的函數
int (*foo(int)) (double*, char);
// 使用 typedef 簡化
typedef int (*FuncPtr)(double*, char);
FuncPtr foo(int);
signal() 原型拆解[cpp]
// 原始聲明(極難讀)
void (*signal(int sig, void (*func)(int))) (int);
// typedef 逐層拆解
typedef void (*SigHandler)(int); // 信號處理函數類型
SigHandler signal(int sig, SigHandler func); // 清晰版本
[cpp]
void printMyName() { printf("liushuaikobe\n"); }
int main() {
void (*f)() = printMyName; // 函數名隱式轉換為地址
f(); // 直接調用
f = &printMyName; // 顯式取址亦可
f();
return 0;
}
| 聲明 | 含義 |
|---|---|
int *p; | 指向 int 的指針 |
int *p[10]; | 10 個 int* 的數組 |
int (*p)[10]; | 指向 10 個 int 數組的指針 |
int *func(); | 返回 int* 的函數 |
int (*func)(); | 指向返回 int 函數的指針 |
int *(*func[])(); | 函數指針數組,每個函數返回 int* |
int (*(*func)())[]; | 指向函數的指針,該函數返回數組指針 |
typedef 分層拆解 複雜聲明,不要硬啃。const 位置決定修飾對象:const int *p(指向常量)vs int *const p(常量指針)。sizeof 失效,需額外傳長度。%p 打印地址,%zu 打印 sizeof 結果。