int a = 9;\
int *aPtr = NULL; // 定義並初始化為空指針\
aPtr = &a; // 取地址賦值\
printf("a=%d, *aPtr=%d\\n", a, *aPtr); // 解引用獲取值\
printf("&a=%p, aPtr=%p\\n", &a, aPtr); // %p 輸出地址\
// * 和 & 互補:&*aPtr == *&aPtr == aPtr
NULL (0) 表示不指向任何對象,唯一可直接賦給指針的整數常量。C 僅支持值傳遞。傳遞指針(地址)可在被調函數中修改主調函數變量。
void swap(int *x, int *y) {\
int t = *x; *x = *y; *y = t;\
}\
int a=1, b=2; swap(&a, &b); // a=2, b=1
| 聲明 | 含義 | 可修改指針值 | 可修改所指值 |
|---|---|---|---|
int *p | 指向非常量的非常量指針 | ✅ | ✅ |
int *const p | 指向非常量的常量指針 | ❌ | ✅ |
const int *p | 指向常量的非常量指針 | ✅ | ❌ |
const int *const p | 指向常量的常量指針 | ❌ | ❌ |
口訣:const 在 * 左修飾所指值,右修飾指針本身。
sizeof(arr) 返回整個數組大小;sizeof(ptr) 返回指針大小(非數組大小)。sizeof(arr)/sizeof(arr[0])。ptr++、ptr--、ptr + n、ptr - n、ptr1 - ptr2。sizeof(指向類型)。int *p; p++ 移動 4 字節。ptr1 - ptr2 返回元素個數差(需同屬一數組)。memcpy、qsort 比較函數)。int a[6] 中 a 為常量指針(指向首元素),a[3] ≡ *(a+3) ≡ *(aPtr+3)。
區別:aPtr = aPtr + 3 合法;a = a + 3 非法(常量不可修改)。
const char *suit[4] = {"Hearts", "Diamonds", "Clubs", "Spades"};\
// 每元素 4/8 字節指針,指向字面量區,共享只讀內存\
// sizeof(suit[i]) == sizeof(char*) == 4/8\
// sizeof(suit) == 4 * sizeof(char*)
對比二維字符數組 char suit[4][10] 固定分配 40 字節,指針數組極大節省空間且支持可變長字符串。
int max(int a, int b);\ int (*p)(int, int) = max;\ int res = (*p)(2, 3); // 或 p(2,3)
int ascending(int a, int b) { return a > b; }\
int descending(int a, int b) { return a < b; }\
\
void bubble(int arr[], int n, int (*cmp)(int, int)) {\
for (int i = 1; i < n; ++i)\
for (int j = 0; j < n - i; ++j)\
if ((*cmp)(arr[j], arr[j+1])) swap(&arr[j], &arr[j+1]);\
}\
\
bubble(a, 10, ascending); // 升序\
bubble(a, 10, descending); // 降序
void func1(int x); void func2(int x); void func3(int x);\
void (*f[3])(int) = {func1, func2, func3};\
(*f[choice])(choice); // 根據輸入分發
int *p = NULL; 或 int *p = &var;。if (p) { ... }。const T*,需修改才用 T*。free(p); p = NULL; 防野指針。指針是 C 語言靈魂,掌握其類型系統、內存模型、算術規則、與數組/函數的轉換關係,才能寫出高效、安全、優雅的系統級代碼。