#include <stdio.h>
struct date {
int year;
int month;
int day;
};
void func(struct date p) {
p.year = 2000;
p.month = 5;
p.day = 22;
}
int main() {
struct date d;
d.year = 1999;
d.month = 4;
d.day = 23;
printf("%d,%d,%d\n", d.year, d.month, d.day);
func(d);
printf("%d,%d,%d\n", d.year, d.month, d.day);
return 0;
}
1999,4,23
1999,4,23
這道題目考察的是 C語言函數參數的傳值呼叫機制。當我們將結構體變數 d 傳遞給函數 func 時,實際上是將結構體的 完整副本 傳遞給了形式參數 p。函數內部對 p 的任何修改,都只影響這個副本,而不會影響主函數中的原始變數 d。
d 佔據一塊記憶體空間,儲存著 {1999, 4, 23}。p 分配新空間,並將 d 的所有成員內容逐位元複製過去。p.year、p.month、p.day,只是改變了副本的值。p 的生命週期結束,棧幀彈出,主函數中的 d 依然保持原值。若需在函數內修改原始結構體,必須傳遞 結構體指標(地址):
void func(struct date *p) {
p->year = 2000;
p->month = 5;
p->day = 2;
}
// 呼叫時
func(&d);
這樣函數拿到的是原始變數的地址,透過指標解參考即可修改原始資料。這也是 C 語言模擬「傳址呼叫」的標準做法。
結構體傳值會產生完整副本,若結構體非常大(如包含大型陣列),頻繁傳值會帶來效能開銷。實務上常見做法:
const struct date * 避免拷貝且防誤改。struct date *。C 語言永遠採用傳值呼叫。函數參數為結構體時,傳遞的是結構體的副本;若需修改實參,必須顯式傳遞指標。這是 C 語言函數機制的基石,也是面試與考試的高頻考點。