首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> C 語言問答

C語言結構體傳值機制解析:函數參數傳遞為何不改變原始數據?

     編輯:C 語言問答

程式碼範例

#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}。
  • 呼叫 func 時:系統在棧上為形參 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 語言模擬「傳址呼叫」的標準做法。

延伸思考:大型結構體的效能考量

結構體傳值會產生完整副本,若結構體非常大(如包含大型陣列),頻繁傳值會帶來效能開銷。實務上常見做法:

  1. 若不需修改原始資料,傳 const struct date * 避免拷貝且防誤改。
  2. 若需修改,傳 struct date *。
  3. 現代編譯器優化下,小型結構體(如本例 3 個 int)傳值開銷極小,甚至可能比傳指標更快(避免間接存取)。

總結

C 語言永遠採用傳值呼叫。函數參數為結構體時,傳遞的是結構體的副本;若需修改實參,必須顯式傳遞指標。這是 C 語言函數機制的基石,也是面試與考試的高頻考點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved