目次
1. 為什麼要學習「參照傳遞」?
在學習 C 語言時,「參照傳遞(指標傳遞)」的概念是無法迴避的。這是許多初學者容易卡住的重點,但若能徹底理解,就能掌握 C 語言的本質與彈性程式設計的能力。 參照傳遞之所以重要,有幾個原因。首先,在 C 語言中傳遞參數時,基本上是「值傳遞」。也就是把呼叫端變數的值複製後傳入函式。因此,即使在函式內更改該值,也不會影響呼叫端的變數。這看起來很安全,但實際上「想在函式內直接改寫呼叫端的值」的情況並不少見。 例如,「交換兩個值的 swap 函式」或「一次更新多個值的處理」等,僅靠值傳遞無法實現。此時就需要參照傳遞,也就是使用指標傳遞參數。利用指標,函式可以參照呼叫端變數的位址,直接修改其值。 此外,參照傳遞不僅用於單純的值更新,當需要有效率地處理陣列、結構體等大型資料時也很有幫助。值傳遞會在每次呼叫函式時複製資料,可能在記憶體與執行速度上造成低效。然而,傳遞指標可省去複製的工作,提升整體程式效能。 如此一來,了解並善用 C 語言中的參照傳遞機制,就能寫出更實用且高效的程式碼。對於初學者而言,起初可能會感到難以理解,但透過反覆學習與實作,必能穩步提升能力。2. 值傳遞與參照傳遞的差異
C語言的函式中傳遞參數的方法有「值傳遞」與「參照傳遞(指標傳遞)」兩種。了解各自的機制與特點,是減少錯誤、讓程式如預期運作的第一步。什麼是值傳遞
值傳遞(call by value)是指在呼叫函式時,將傳入變數的「值」複製後傳遞給函式的參數。例如,請看以下程式碼。void func(int x) {
x = 10;
}
int main() {
int a = 5;
func(a);
printf("%dn", a); // 輸出為5
}
在此情況下,a
的值(5)會被複製到 func
函式的 x
。即使在函式內修改 x
,main
函式內的 a
也不會受到任何影響。這可以理解為「原始變數保持不變」「僅在操作複製的值」。什麼是參照傳遞(指標傳遞)
另一方面,參照傳遞(call by reference)是傳遞變數的「位址(位置)」的方法。C 語言沒有直接的參照型別,但可透過「指標」實現與參照傳遞等同的功能。 例如如下範例。void func(int *x) {
*x = 10;
}
int main() {
int a = 5;
func(&a);
printf("%dn", a); // 輸出為10
}
此處重要的是,func(&a);
傳遞了變數 a
的位址(位置)。而在 func
函式內,透過寫成 *x
,即可直接存取該位址所指向的「真實 a」並修改其值。值傳遞與參照傳遞的差異總結
方式 | 傳遞的內容 | 函式內的變更 | 對呼叫端的影響 |
---|---|---|---|
值傳遞 | 值(複製) | 不會反映 | 無 |
參照傳遞 | 位址 | 會反映 | 有 |
3. 透過程式碼了解!實作範例 3 個
在此,我們將使用 C 語言的程式碼,以三個範例說明「參照傳遞(指標傳遞)」的具體用法。透過程式碼,體驗其運作差異與優點。1. 基本的參照傳遞範例
首先,示範使用指標在函式內修改變數值的基本範例。void increment(int *p) {
(*p)++;
}
int main() {
int a = 0;
increment(&a);
printf("%dn", a); // 輸出: 1
return 0;
}
在此範例中,increment
函式以 int *p
形式接收地址作為參數。透過 (*p)++
,呼叫端的變數 a
會在函式內直接被修改。這就是參照傳遞的基本概念。2. swap 函式的實作範例
若想交換兩個變數的值,值傳遞無法實現,但使用參照傳遞(指標傳遞)則相當簡單。void swap(int *x, int *y) {
int temp = *x;
*x = *y;
*y = temp;
}
int main() {
int a = 3, b = 7;
swap(&a, &b);
printf("a = %d, b = %dn", a, b); // 輸出: a = 7, b = 3
return 0;
}
swap
函式接受兩個整數指標並交換其內容。呼叫時傳入 &a, &b
的地址即為重點。3. 陣列與參照傳遞
在 C 語言中,將陣列名稱傳遞給函式時,會直接傳遞其首位地址(指標)。這實際上就是參照傳遞。void fill_zero(int arr[], int size) {
for (int i = 0; i < size; i++) {
arr[i] = 0;
}
}
int main() {
int data[5] = {1, 2, 3, 4, 5};
fill_zero(data, 5);
for (int i = 0; i < 5; i++) {
printf("%d ", data[i]);
}
// 輸出: 0 0 0 0 0
return 0;
}
在此情況下,fill_zero
函式內亦能直接修改陣列 data
的內容。這也是 C 語言特有的參照傳遞之一。 如此一來,當需要透過函式直接操作值,或想有效處理陣列等大型資料時,參照傳遞非常有用。實際執行程式碼即可清楚體會其便利性。4. 為什麼要使用參照傳遞?優點與注意事項
參照傳遞(指標傳遞)是為了在 C 語言中撰寫更具彈性且高效的程式而重要的手法。此處將說明使用參照傳遞的主要優點,以及使用時需要注意的要點。參照傳遞的優點
- 可直接從函式修改呼叫端的值 在值傳的情況下,函式內部對值的修改不會影響呼叫端,但使用參照傳遞時可以直接改寫作為參數傳入的變數本身。例如 swap 函式或數值的加減等,想以非返回值的形式返回處理結果時非常方便。
- 有效處理大型資料 在將陣列或結構體等大型資料傳遞給函式時,若使用值傳遞會全部複製,導致不必要的記憶體消耗與處理速度下降。使用參照傳遞(指標傳遞)只傳遞位址(位置),因此省去複製的麻煩,效率更高。
- 可同時修改多個值 在值傳遞時只能返回一個返回值,但使用參照傳遞可以一次性修改多個變數的值。由此函式的彈性大幅提升。

參照傳遞的注意點與缺點
- 容易產生副作用 因為可以直接修改呼叫端的資料,程式中哪裡改寫了值往往不易追蹤。在大型程式或多人開發時,可能成為意外錯誤的根源,需要特別留意。
- 指標使用錯誤導致的錯誤 若未正確管理位址(指標),會產生意外的問題。例如誤參考 NULL 指標,或存取已釋放的記憶體導致程式崩潰,這些都是 C 語言特有的「危險性」。
- 可讀性與理解難度 大量使用指標的程式碼往往讓初者難以理解。此外,若錯誤使用「&」或「*」等符號,容易產生預期外的行為。
5. C++的差異(補充說明)
學習 C 語言時,會遇到「參照傳遞」這個詞彙在 C++ 中也會出現,容易造成混淆。這裡簡單整理 C 語言與 C++ 的「參照傳遞」差異。C 語言的參照傳遞=指標傳遞
在 C 語言中即使說「參照傳遞」,實際上是使用「指標」將變數的位址傳遞給函式。函式端使用指標,透過改寫該位址指向的值,讓呼叫端的變數產生變化。void func(int *x) {
*x = 100;
}
int main() {
int a = 0;
func(&a);
// a 會變成 100
return 0;
}
如此一來,必須在參數前加上*
以接受指標型別,呼叫時則以&a
的方式傳遞位址。C++ 的參照傳遞更簡潔
另一方面,C++ 提供「參照型別(reference)」的機制作為語言規格。變數宣告時使用&
,以「參照」的方式接受參數,便能在函式內直接操作呼叫端的變數本身。與指標不同的是,無需使用特殊運算子,感覺上就像一般變數一樣使用,這是其特點。void func(int &x) {
x = 100;
}
int main() {
int a = 0;
func(a);
// a 會變成 100
return 0;
}
C++ 的參照型別因為減少了遺漏傳遞位址或指標操作失誤,所以更安全且直觀。此外,C++ 可依需求在指標傳遞與參照傳遞之間切換使用。總結:使用方式的差異
- C 語言:參照傳遞=使用指標(
*
與&
皆為必須) - C++:參照傳遞=以參照型別接受(僅
&
即可,無需指標操作)
6. FAQ 常見問題
在此,我們將以問答形式彙總學習者對「C 語言 參照傳遞」常有的疑問。讓我們解決實際常見的混亂與工作中的卡點。問題1:C 語言中將陣列傳遞給函式為何會變成參照傳遞?
在 C 語言中,將陣列名稱傳遞給函式時,會自動傳遞「陣列的起始位址(指標)」。因此在函式內修改陣列元素,會直接反映到呼叫端的陣列。這不是值傳遞,而是實質上的參照傳遞(指標傳遞),可以這樣理解。問題2:如果在函式內改變指標的值(位址)本身會怎樣?
即使在函式內更改指標變數本身的值(即指向的位址),也不會影響呼叫端的指標。若要修改呼叫端的指標變數本身,必須使用「指標的指標(雙重指標)」。問題3:結構體也能使用參照傳遞嗎?
是的,將結構體以指標形式傳遞給函式即可實現參照傳遞。若使用值傳遞,整個結構體會被複製,但使用指標傳遞則能更有效率地處理資料。struct Data {
int value;
};
void update(struct Data *d) {
d->value = 123;
}
問題4:使用參照傳遞時,需要哪些安全措施?
使用指標時,「NULL 檢查」與「是否為有效位址」的確認非常重要。若不慎參照了無效位址,程式可能會當機,因此在函式內應使用if (ptr != NULL)
等檢查。另外,使用 malloc 動態配置的記憶體也需在適當時機釋放(free),這同樣重要。問題5:在 C 與 C++ 中使用參照傳遞,該選哪一個?
在 C 語言中,使用指標來實現參照傳遞;而在 C++ 中,則可使用參照型(例如int &x
),因此在可讀性與安全性方面,建議使用 C++ 的參照型。但在低階控制或與其他語言的整合時,對 C 語言指標的理解仍然是必須的。請依據目的與專案方針來選擇。