指標變數只存放地址。int *ip; 宣告一個存放 int 位址的變數。將整數直接賦給指標(ip = 100;)是非法且危險的。
& 與解參考 *
int i = 200, x;
int *ip;
ip = &i; // ip 存放 i 的地址(假設 1800)
x = *ip; // *ip 訪問地址 1800 處的 int 值 → x = 200
記憶體圖解:
ip (address: 2000) i (address: 1800) ┌─────────┐ ┌─────────┐ │ 1800 │ ──────────────► │ 200 │ └─────────┘ └─────────┘
int i = 'a', j = 'b';
int *p1 = &i, *p2 = &j;
p2 = p1; // p2 現在也指向 i
圖解:
p1 ──► i ('a') p2 ──► i ('a') (p2=p1 後)
p2 ──► j ('b') j ('b') 無指標指向
*p2 = *p1 vs p2 = p1| 運算式 | 語義 | 效果 | 圖解 |
|---|---|---|---|
p2 = p1 | 指標賦值 | p2 指向 p1 所指物件 | 兩指標指向同一記憶體 |
*p2 = *p1 | 間接賦值 | 將 p1 指向的值複製到 p2 指向的記憶體 | 兩記憶體值相同,指向不變 |
// *p2 = *p1 等價於 j = i (若 p1=&i, p2=&j)
// 但速度較慢、意圖不明確,除非「指向目標在執行期才決定」
*px 可出現在 x 合法的任何位置:
int x, y, *px = &x;
y = *px + 5; // y = x + 5
y = ++*px; // 先增後用:x=x+1; y=x; 等價 ++(*px)
y = *px++; // 先用後增:y=x; px=px+1; 等價 *(px++)
優先級提醒:++*px = ++(*px),*px++ = *(px++)。
int arr[5] = {10, 20, 30, 40, 50};
int *p = arr; // p 指向 arr[0]
p + 1; // 指向 arr[1] (地址 + sizeof(int))
p + 2; // 指向 arr[2]
p++; // 移動到下一元素
p--; // 移動到上一元素
p2 - p1; // 兩指標相減 → 元素個數差 (僅同一陣列合法)
核心規則:指標加減的單位是所指型別大小,非位元組。int* +1 移動 4 bytes,double* +1 移動 8 bytes。
p1 < p2 表示 p1 指向較低位址元素NULL (0) 比較:p == NULL 表示空指標
#include
int main(void) {
int a, b, c, *pmax, *pmin;
printf("Input three numbers: ");
scanf("%d%d%d", &a, &b, &c);
if (a > b) { pmax = &a; pmin = &b; }
else { pmax = &b; pmin = &a; }
if (c > *pmax) pmax = &c;
if (c < *pmin) pmin = &c;
printf("Max = %d, Min = %d\n", *pmax, *pmin);
return 0;
}
此例展示指標如何「延遲綁定」變數身份,執行期決定指向哪個變數。
| 層面 | 直接存取 | 指標間接存取 |
|---|---|---|
| 速度 | 快(單指令) | 慢(額外載入指標、間接定址) |
| 直觀度 | 高 | 低(需追蹤指標指向) |
| 靈活性 | 低(編譯期綁定) | 高(執行期動態綁定) |
| 適用場景 | 固定資料流 | 動態資料結構、多態、回調 |
指標是 C 語言的靈魂:& 取址建立連結,* 解參考跟隨連結,指標運算在同類陣列中導航。理解「指標存地址、解參考取值、運算單位是型別大小」三大核心,並養成「初始化、檢查空指標、釋放置空」防衛習慣,即可駕馭從簡單資料操作到複雜資料結構的所有指標場景。