void swap(int x, int y) 只能交換副本,**無法修改主調函數的實參**。必須傳遞變量地址,在被調函數中通過指針間接訪問並修改原內存。
#include <stdio.h>
void swap(int* x, int* y) {
int temp = *x; // 取出 x 指向內存的值
*x = *y; // 將 y 指向內存的值寫入 x 指向內存
*y = temp; // 將暫存值寫入 y 指向內存
}
int main() {
int m = 1, n = 2;
printf("調用前: m=%d, n=%d\n", m, n); // m=1, n=2
swap(&m, &n); // 傳遞地址
printf("調用後: m=%d, n=%d\n", m, n); // m=2, n=1
return 0;
}
| 階段 | main 棧幀 | swap 棧幀 | 操作 |
|---|---|---|---|
| 調用前 | m: 1n: 2 | — | — |
| 進入 swap | 同上 | x: &my: &ntemp: ? | 形參接收實參地址 |
temp = *x | 同上 | temp: 1 | 解引用 x 讀取 m 的值 |
*x = *y | m: 2 | 同上 | 解引用 y 讀取 n 的值寫入 m |
*y = temp | n: 1 | 同上 | 寫入暫存值到 n |
| 返回 main | m: 2, n: 1 | 銷毀 | 交換完成 |
// swap(&m, &n) 內聯展開後等價於:
int* x = &m;
int* y = &n;
int temp = *x; // temp = m
*x = *y; // m = n
*y = temp; // n = temp (原 m)
指針參數本質是將「值傳遞」升級為「引用傳遞」的手動實現:傳遞地址值(仍是值傳遞),但在函數內通過解引用操作原內存。
| 錯誤代碼 | 現象 | 原因 | 修正 |
|---|---|---|---|
void swap(int x, int y) | 主調變量不變 | 值傳遞只操作副本 | 改為 int* x, int* y,調用傳 &a, &b |
void swap(int* x, int* y) { int* t=x; x=y; y=t; } | 主調變量不變 | 只交換了局部指針變量,未解引用修改內存 | 必須 *x = *y 操作指向的內存 |
swap(m, n) 無取地址 | 編譯錯誤/運行崩潰 | 傳入整數值當指針,解引用訪問非法地址 | 必須 swap(&m, &n) |
void func(const int* p):承諾不修改 *p 指向的數據(只讀)。void func(int* const p):承諾不修改指針 p 本身(不指向別處)。void func(const int* const p):雙重承諾。良好習慣:只讀參數加 const,讓編譯器幫你檢查誤寫,文檔化接口契約。
C 語言無引用語法,**指針是模擬引用的唯一標準手段**。理解 &var 取地址、*ptr 解引用、形參接收地址並在函數內解引用修改原內存,這三步串聯起來,就是 C 語言「傳遞引用」的完整鏈路。