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

C語言變量記憶體分配全景圖:棧、堆、全域/靜態、常量區與代碼區

     編輯:關於C

經典困惑:為何字串字面量能返回,區域陣列卻不行?

// 情況 A:正確
char* f1() { char *s = "abcdefghijkl"; return s; }

// 情況 B:錯誤(回傳區域變量地址)
char* f2() { char s[] = "abcdefghijkl"; return s; }

差異本質:字串字面量存於常量區(程式結束前釋放),區域陣列存於棧(函數返回即銷毀)。

五大記憶體區域總覽

區域管理方式存放內容生命週期
棧編譯器自動函數參數、區域變量、返回地址函數調用期間
堆程式員手動 malloc/free 或 new/delete動態分配記憶體手動釋放或程式結束由 OS 回收
全域/靜態區編譯器靜態分配全域變量、static 變量(已初始化/未初始化分段)程式全生命週期
常量區編譯器字串字面量、const 修飾的全域/靜態變量程式全生命週期
代碼區編譯器函數二進制機器碼程式全生命週期

實例圖解:變量落區判斷

int a = 0;           // 全域初始化區
char *p1;            // 全域未初始化區
void func() {
    int b;           // 棧
    char s[] = "abc"; // 棧(內容複製自常量區)
    char *p2;        // 棧
    char *p3 = "123456"; // p3在棧,"123456\0"在常量區
    static int c = 0; // 全域/靜態初始化區
    p1 = malloc(10);  // 堆
    p2 = malloc(20);  // 堆
    strcpy(p1, "123456"); // 字面量在常量區,可能與 p3 共享
}

棧 vs 堆 深度對比

維度棧堆
分配方式系統自動程式員手動
空間大小受限(Windows 預設 1~2MB)受限於虛擬記憶體,極大
生長方向高位→低位低位→高位(鏈表管理)
分配效率極快(指針移動)較慢(尋找合適塊、分裂合併)
碎片問題無易產生外部碎片
適用場景小型、生命週期短、大小固定大型、動態、生命週期不定

存取效率實測:陣列 vs 指針

char a[] = "1234567890"; // 棧上陣列
char *p  = "1234567890"; // 指向常量區
a[1]; // 編譯為 mov cl, [ebp-0Fh]      直接偏移訪問
p[1]; // 編譯為 mov edx, [ebp-14h]; mov al, [edx+1]  間接訪問,多一條指令

結論:棧上陣列存取比指針指向的常量區/堆區更快。

最佳實踐建議

  1. 大陣列/結構體改用 static 或動態分配,避免棧溢位
  2. 字串字面量賦值給 const char*,防止誤修改觸發段錯誤
  3. 嵌入式/高效能場景考慮記憶體池替代頻繁 malloc/free
  4. Windows 下大塊記憶體優先 VirtualAlloc 直接保留位址空間
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved