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

C/C++ 記憶體管理實戰(三):sizeof 陷阱、指標參數傳遞記憶體的正確姿勢

     編輯:VC 教學

7.3.3 計算記憶體容量

sizeof 可計算陣列容量(位元組數)。

  • char a[] = "hello world"; → sizeof(a) = 12(含 \0)。
  • char* p = a; → sizeof(p) = 4(32 位元系統指標大小),非 p 所指記憶體大小。C/C++ 無法從指標得知所指記憶體大小,除非配置時記住它。

陣列作參數會退化為指標


void Func(char a[100]) {
    cout << sizeof(a) << endl; // 輸出 4,而非 100!
}

無論宣告 char a[100] 或 char a[],參數傳遞時一律退化為 char*,sizeof 只能得知指標大小。

7.4 指標參數如何傳遞記憶體?

錯誤示範:嘗試在函式內用指標參數配置動態記憶體:


void GetMemory(char* p, int num) {
    p = (char*)malloc(sizeof(char) * num); // 只修改區域副本 _p
}
void Test() {
    char* str = NULL;
    GetMemory(str, 100); // str 仍為 NULL
    strcpy(str, "hello"); // 執行期錯誤
}

原因:編譯器為參數建立區域副本 _p,_p = p。函式內修改 _p 指向新記憶體,不影響外部 p。且每次呼叫洩漏一塊記憶體(未 free)。

正解一:指向指標的指標(二級指標)


void GetMemory2(char** p, int num) {
    *p = (char*)malloc(sizeof(char) * num);
}
void Test2() {
    char* str = NULL;
    GetMemory2(&str, 100); // 傳遞 &str
    strcpy(str, "hello");
    cout << str << endl;
    free(str);
}

正解二:用函式回傳值傳遞動態記憶體(更簡單)


char* GetMemory3(int num) {
    char* p = (char*)malloc(sizeof(char) * num);
    return p;
}
void Test3() {
    char* str = GetMemory3(100);
    strcpy(str, "hello");
    cout << str << endl;
    free(str);
}

⚠ 回傳指標的致命陷阱:勿回傳指向「堆疊記憶體」的指標


char* GetString() {
    char p[] = "hello world"; // 位於堆疊
    return p; // 編譯器警告:回傳區域變數位址
}
void Test4() {
    char* str = GetString(); // str 內容為垃圾
    cout << str << endl;
}

區域陣列 p 在函式結束時自動銷毀,回傳其位址屬未定義行為。

回傳常數字串雖能執行但概念錯誤


char* GetString2() {
    char* p = "hello world"; // 常數字串在靜態區
    return p;
}

執行不出錯,但設計錯誤:GetString2 總是回傳同一塊唯讀靜態記憶體,呼叫端若嘗試修改會崩潰。

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