函數參數永遠是將實參的「值」複製給形參。若要在函數內修改呼叫端變數,必須傳遞該變數的「位址」(指標),再透過解參考操作間接修改。
#include
// 值傳遞:形參是實參的副本,修改不影響原變數
void pass_by_value(int a) {
a++;
printf("在 pass_by_value 內:a = %d\n", a); // 2
}
// 位址傳遞:形參是指標,指向實參記憶體位置
void pass_by_address(int *a) {
(*a)++;
printf("在 pass_by_address 內:*a = %d\n", *a); // 2
}
int main(void) {
int n = 1;
printf("呼叫前:n = %d\n", n); // 1
pass_by_value(n);
printf("呼叫 pass_by_value 後:n = %d\n", n); // 1(未變)
pass_by_address(&n); // 傳遞 n 的位址
printf("呼叫 pass_by_address 後:n = %d\n", n); // 2(已變)
return 0;
}
| 特性 | 值傳遞 | 位址傳遞 |
|---|---|---|
| 形參型別 | int | int * |
| 實參形式 | n | &n |
| 函數內修改方式 | a = 10 | *a = 10 |
| 對原變數影響 | 無 | 有 |
| 適用場景 | 輸入參數、小型結構體 | 輸出參數、大型結構體、陣列、需修改原值 |
void divide(int dividend, int divisor, int *quotient, int *remainder) {
if (divisor == 0) return; // 錯誤處理略
*quotient = dividend / divisor;
*remainder = dividend % divisor;
}
int main() {
int q, r;
divide(10, 3, &q, &r);
printf("商=%d 餘=%d\n", q, r); // 商=3 餘=1
}
void func(int *p) { p = &local_var; } —— 修改的是區域指標副本,不影響呼叫端指標。void func(int **p) { *p = &local_var; } —— 傳遞指標的指標(雙重指標)才能修改呼叫端指標本身。restrict 關鍵字(C99)告知編譯器指標不重疊,啟用更激進最佳化。「值傳遞」是 C 語言參數機制的唯一真相;「位址傳遞」是透過傳遞位址值來實現的間接修改技巧。熟練掌握兩者轉換,是編寫靈活、高效 C 函數介面的基石。