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

C 語言指針參數傳遞陷阱:為什麼函數內修改指針不影響外部?

     編輯:程式設計疑難解答

問題代碼還原

void GetPtr(char* p1) {
    p1 = "szkde"; // 修改形參指向
    // 分配內存未釋放 → 內存洩漏
    char* leak = malloc(100);
}

int main() {
    char* p1 = "abcdefg";
    GetPtr(p1);
    printf("%s\n", p1); // 輸出仍為 "abcdefg"
    return 0;
}

現象解析

  • 輸出:abcdefg(非預期的 szkde)
  • 內存洩漏:函數內 malloc 未釋放,且指針未返回。

核心原理:值傳遞機制

C 語言只有值傳遞。調用 GetPtr(p1) 時,將 p1 的地址值(如 0x7fff...)複製給形參 p1。函數內修改形參 p1 的指向,只是改變了副本指向的地址,不影響實參 p1 的值。

內存圖解

調用前:
main棧幀: p1 @ 0x1000 → "abcdefg" (常量區)

調用 GetPtr(p1):
GetPtr棧幀: p1(形參) @ 0x2000 → 0x1000 (複製實參值)

函數內 p1 = "szkde":
GetPtr棧幀: p1(形參) @ 0x2000 → "szkde" (常量區)
main棧幀: p1 @ 0x1000 → "abcdefg" (完全不變)

函數返回:GetPtr棧幀銷毀,形參消失,main中p1依然指向"abcdefg"

正確修改外部指針的兩種方案

方案一:傳遞指針的指針(二級指針)

void GetPtr(char** p1) { // 接收指針地址
    *p1 = "szkde"; // 解引用修改實參指向
}

int main() {
    char* p1 = "abcdefg";
    GetPtr(&p1); // 傳遞 p1 的地址
    printf("%s\n", p1); // 輸出 "szkde"
}

方案二:返回新指針(推薦,更符合 C 風格)

char* GetPtr() {
    return "szkde"; // 或返回 malloc 內存,調用者負責 free
}

int main() {
    char* p1 = "abcdefg";
    p1 = GetPtr(); // 接收返回值更新指針
    printf("%s\n", p1);
}

內存洩漏補充

void GetPtr(char* p1) {
    char* leak = malloc(100); // 分配內存
    // 無 free,無返回,地址丟失 → 內存洩漏
}

修復:若函數內分配內存,必須通過返回值或二級指針傳回給調用者,由調用者 free。

總結

  • C 語言參數傳遞本質是值拷貝,指針傳遞的是地址值的拷貝。
  • 要在函數內修改外部指針指向,需傳遞指針的指針(二級指針)或返回新指針。
  • 函數內分配內存必須有明確歸屬,避免洩漏。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved