指標是 C 語言家族的核心特性,Objective-C 繼承了其完整語義。理解指標機制不僅能寫出高效能代碼,更是掌握記憶體管理、Block 實現、Runtime 機制的基石。本文系統梳理指標從基本語法到進階應用的知識體系。
變數值的存取分兩種模式:
int a = 10;)。int *p = &a;)。指標變數本質是一個「存放記憶體位址的變數」,其型別決定了解讀時的位元組寬度與解釋方式。
類型 *指標名; // 宣告語法,如 int *ptr;
兩個關鍵單目運算子:
&(取址運算子):獲取變數的記憶體位址。*(間接運算子/解引用):讀取指標指向位址處的值。int *p; 而非 int p;。int * 僅能指向 int,指向 float 需顯式轉型,否則編譯器報警/報錯。C 語言預設「傳值呼叫」,函數內修改參數不影響外部實參。若需修改外部變數,必須傳遞其位址:
void swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
int main() {
int m = 5, n = 9;
swap(&m, &n); // 傳遞位址
NSLog(@"%d, %d", m, n); // 輸出 9, 5
return 0;
}
原理:*a 解引用指向 m 的記憶體,直接修改該位址內容,故外部變數值改變。
int arr[5]; arr == &arr[0]; // 等價,但 arr 為常量指標,不可修改
int *p, *pt, a, arr[10]; p = &a; // 變數位址 p = &arr[i]; // 陣列元素位址 p = arr; // 陣列首位址(隱式轉型) p = pt; // 指標間賦值
p + n:位址位移 n * sizeof(型別) 位元組。ptrdiff_t 型別)。陣列名代表固定位址,不可作為左值(arr++ 非法)。
void sort(int arr[], int n); // 等價於 void sort(int *arr, int n);
函數內對陣列元素的修改直接影響原陣列。這也是快速排序等演算法高效運作的基礎。
C 風格字串本質是 char[],以 \0 結尾。字串指標 char *str 指向首字符。
"hello")存放於唯讀區,char *s = "hello"; 中 s 不可修改內容。char s[] = "hello";)存放於堆疊,內容可修改,但陣列名不可重新賦值。int (*funcPtr)(int, int); // 指向「接受兩 int 回傳 int」的函數 funcPtr = add; // 賦值函數名(隱式轉址) funcPtr = &add; // 顯式取址,等價
int result = (*funcPtr)(3, 5); // 或 funcPtr(3, 5); 現代編譯器支援省略 *
當演算法框架固定但具體邏輯可變時(如 qsort 比較函數),以函數指標作參數注入行為:
void process(int *data, int n, int (*cmp)(int, int)) { ... }
需確保回傳指標指向的函數生命週期超過調用者:
static 修飾)安全。int *ptrArray[10]; // 10 個 int 指標的陣列 // 注意區別:int (*p)[10] 是「指向 10 元素 int 陣列的指標」
常用於命令列參數 char *argv[]、字串表查找等場景。
指標機制將「資料位址」显式化,賦予程式設計師對記憶體佈局的精確控制力。從參數傳遞、陣列操作、字串處理到回調架構、動態派發,指標無處不在。深入理解其型別系統、算術規則與生命週期語義,是寫出健壯、高效 C/Objective-C 代碼的關鍵。