// 推薦:靠近變數名,強調「p 是指針」
int *p, *q; // p, q 都是 int*
// 避免:靠近類型,易誤導
int* p, q; // p 是 int*, q 是 int (陷阱!)
// 最佳:逐行聲明或用 typedef
typedef int *IntPtr;
IntPtr p, q; // 明確雙方都是指針
int *p; // 危險:野指針 (隨機地址)
int *p = NULL; // 安全:空指針 (明確無效)
int *p = # // 正確:指向有效對象
// 使用前檢查
if (p) { *p = 10; } // 防空指針解引用崩潰
| 聲明 | 口訣 | 指針可變? | 值可變? | 典型用途 |
|---|---|---|---|---|
const int *pint const *p | 指向常量的指針 (Pointer to const) | 是 | **否** (通過 p) | 函數參數 `const char *str` 保護只讀 |
int *const p | 常量指針 (Const pointer) | **否** (初始化後不可改) | 是 | 固定緩衝區指針、硬體暫存器基址 |
const int *const p | 指向常量的常量指針 | 否 | 否 | 只讀查找表、字串常量指針 |
int *p | 普通指針 | 是 | 是 | 一般修改數據 |
閱讀技巧:從右向左讀 `const` 最近修飾誰。`int *const p` → `p` 是 `const` (指針常);`const int *p` → `int` 是 `const` (值常)。
int arr[5] = {10,20,30,40,50};
int *p = arr; // 陣列名退化為首元素地址
printf("%d\n", *p); // 10
printf("%d\n", *(p+1)); // 20 (p+1 移動 sizeof(int) 位元組)
p++; // 指向下一個 int
printf("%d\n", p[2]); // 40 (p[2] == *(p+2))
// 類型決定步長
char *cp = (char*)p; // 強轉 char*,步長變 1 位元組
// 危險:違反嚴格別名規則,僅用於字節流操作 (memcpy 等)
int val = 100;
int *p1 = &val; // 一級
int **p2 = &p1; // 二級:指向指針的指針
int ***p3 = &p2; // 三級
**p2 = 200; // 修改 val
// 應用:函數修改指針本身 (輸出參數)
void allocate(int **out_ptr, size_t n) {
*out_ptr = malloc(n * sizeof(int));
}
int *buf; allocate(&buf, 10);