| 規則 | 說明 |
|---|---|
& 運算元限制 | 僅能用於記憶體中物件 (變數、陣列元素),不可用於表達式、常數、register 變數 |
* 間接引用 | 作用於指標,存取指向的物件 |
| 指標型別嚴格性 | 指標只能指向特定型別,void* 可存放任意指標但不可直接解引用 |
C 永遠傳值:函數收到的是引數副本,無法直接修改呼叫端變數。
// 錯誤嘗試:無法修改 main 的 x, y
void swap_wrong(int x, int y) {
int t = x; x = y; y = t; // 只修改區域副本
}
傳遞變數位址,函數透過解引用修改原變數:
#include
void swap(int *x, int *y);
int main() {
int m = 1, n = 2;
swap(&m, &n); // 傳遞位址
printf("m=%d n=%d\n", m, n); // 輸出: m=2 n=1
return 0;
}
void swap(int *x, int *y) {
int temp = *x; // 解引用取值
*x = *y; // 解引用賦值
*y = temp;
}
main 堆疊幀: swap 堆疊幀:
+----------+ +----------+
| m: 1 | ←──┐ | x: &m | ──┐
+----------+ │ +----------+ │
| n: 2 | ←──┘ | y: &n | ──┘
+----------+ | temp: 1 |
+----------+
*x 即 *(&m) 即 m
*y 即 *(&n) 即 n
// swap 內部操作等價於:
int *x = &m;
int *y = &n;
temp = *(&m); // temp = m
*(&m) = *(&n); // m = n
*(&n) = temp; // n = temp
| 特性 | C 語言 | Java |
|---|---|---|
| 基本型別 | 傳值 (副本) | 傳值 (副本) |
| 物件/陣列 | 無物件概念,陣列退化為指標 | 傳參考副本 (可修改物件內容) |
| 修改呼叫端變數 | 必須傳位址 (&var) | 基本型別不可,物件可修改內部狀態 |
| 交換函數實作 | 傳指標 swap(int*, int*) | 基本型別不可實作,需包裝類或陣列 |
// 僅讀取,不修改 → 加 const
void print_int(const int *p) {
printf("%d", *p); // 安全
// *p = 10; // 編譯錯誤
}
// 修改指向的資料 → 不加 const
void set_int(int *p, int val) {
*p = val; // 正確
}
// 修改指標本身 (罕見) → 指標的指標
void reallocate(int **p, size_t n) {
*p = realloc(*p, n * sizeof(int));
}
int *p; func(p); → 垃圾位址崩潰int *p = NULL; *p = 1;float f; int *p = &f; → 違反嚴格別名規則void f(int a[]) { sizeof(a); } → a 退化為指標,sizeof 回傳指標大小constfree