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

C 語言結構體參數傳遞:值傳遞 vs 指針傳遞的區別與常見錯誤

     編輯:程式設計疑難解答

問題代碼

typedef struct {
    char name[10];
    char sex;
    long num;
} ElemType;

typedef struct {
    ElemType *elem;   // 動態數組指針
    int length;
    int listsize;
} SqList;

// 錯誤函數:值傳遞結構體
void MergeList_Sq(SqList La, SqList Lb, SqList *Lc) {
    ElemType *pa, *pb;
    pa = La->elem;  // 編譯錯誤:La 不是指針,無法用 ->
    pb = Lb->elem;
    // ...
}

錯誤原因

  • 函數參數 `SqList La, SqList Lb` 是值傳遞,函數內收到的是結構體**副本**。
  • 副本內的指針 `elem` 指向原數據 (淺拷貝),但結構體變量本身 `La`、`Lb` 是局部變量,**不是指針**,不能用 `->` 訪問成員,只能用 `.`。
  • 若在函數內修改 `La.length` 等非指針成員,**不會影響原調用者的結構體**。

修正方案:統一使用指針傳遞

// 正確聲明:所有可修改或涉及指針操作的結構體參數用指針
void MergeList_Sq(SqList *La, SqList *Lb, SqList *Lc) {
    ElemType *pa = La->elem;  // 正確:La 是指針,用 ->
    ElemType *pb = Lb->elem;
    // ...
}

// 調用時取地址
SqList listA, listB, listC;
MergeList_Sq(&listA, &listB, &listC);

值傳遞 vs 指針傳遞對比

維度值傳遞 (Struct)指針傳遞 (Struct*)
語法訪問`param.member``param->member`
內存開銷拷貝整個結構體 (含指針成員)僅拷貝指針大小 (4/8 字節)
修改原結構體不可 (修改副本)可 (修改原對象)
修改指針指向的數據可 (淺拷貝指向同一塊內存)可
適用場景小型、只讀、無指針成員結構體大結構體、需修改、含動態內存指針、鏈表節點

本例具體分析

  • `SqList` 含動態數組指針 `elem`,**必須用指針傳遞**,否則函數內無法正確操作原數據鏈,且值傳遞拷貝結構體無意義。
  • 錯誤代碼 `pa = La->elem` 試圖用指針語法訪問值參數,導致編譯失敗。
  • 修正為 `SqList *La` 後,`La->elem` 正確訪問原結構體的 `elem` 指針。

進階:const 正確性

// 僅讀取不修改結構體本身 (但可修改 elem 指向的數據)
void ReadOnlyFunc(const SqList *list) {
    // list->length = 10; // 編譯錯誤:不能修改 length
    list->elem[0].num = 100; // 允許:修改指向的數據
}

// 完全只讀 (指針指向的數據也不修改)
void ReadOnlyData(const SqList *const list) { // 或 const ElemType *elem
    // ...
}

總結

C 語言結構體參數傳遞**默認值傳遞 (拷貝)**。含指針成員、需修改、或較大結構體**必須用指針傳遞**。錯誤代碼將值參數誤當指針用 `->` 訪問,修正為指針參數並配合 `&` 調用即可。養成「結構體參數默認指針,只讀加 `const`」的習慣。

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