1. 程式人生 > >C程序存儲結構

C程序存儲結構

int uno 棧區 ria .html 源代碼 外部 來源 n)

使用windows平臺MinGW版本的GCC編譯器,對以下代碼片段進行了編譯,探究各個變量在內存中的存儲位置:

(不同的機器、不同的操作系統的GCC版本可能有差異,因此結論不具有普遍適用性,具體情況需要編譯執行此代碼自行分析)

代碼片段:

#include <stdio.h>
#include <stdlib.h>
int k1 = 1;
int k2;
static int k3 = 2;
static int k4;
int main()
{
static int m1 = 2, m2;
int i = 1;
char *p, *p2;
char str[10] = "hello";
char *q = "hello";
p = (char *)malloc(100);
p2 = (char *)malloc(100);
free(p);
free(p2);
printf("棧區-變量地址 i:%p\n", &i);
printf("棧區-變量地址 p:%p\n", &p);
printf("棧區-變量地址 str:%p\n", str);
printf("棧區-變量地址 q:%p\n", &q);
printf("堆區-動態申請 p: %p\n", p);
printf("堆區-動態申請 p2: %p\n", p2);
printf("全局外部有初值 k1: %p\n", &k1);
printf("全局外部無初值 k2: %p\n", &k2);
printf("靜態外部有初值 k3: %p\n", &k3);
printf("靜態外部無初值 k4: %p\n", &k4);
printf("內靜態有初值 m1: %p\n", &m1);
printf("內靜態無初值 m2: %p\n", &m2);
printf("文字常量地址 : %p, %s\n", q, q);
printf("程序區地址 : %p\n", &main);
return 0;
}

運行結果:

技術分享圖片

分析:

(在保存程序之前編譯器應該還要進行預處理進行宏替換等,因為沒有詳細讀過《編譯原理》,暫不討論)

1. 編譯器先保存程序內容,所以程序區在內存的地址最小;

2. 編譯器優先保存已經賦值初始化的全局變量和靜態變量:按照全局外部變量->靜態外部變量->靜態內部變量的順序依次存儲;

3. 編譯器保存過已經賦值初始化的全局變量和靜態變量後,開始處理並保存文字常量;

4. 編譯器處理並保存文字常量後,開始保存沒有賦初始值的全局變量和靜態變量:按照靜態外部變量->靜態內部變量->全局外部變量的順序依次存儲;

5. 將方法的局部變量入棧(因為討論變量,方法的地址指針暫不討論)。因為棧的存儲規律是後進先出,所以最後定義的變量先入棧,即存在較小的地址,所以也可以推出程序執行時的內存尋址是由低到高。

6. 最後將動態申請的變量按先進先出的順序存入堆區。

總結如下圖所示:

技術分享圖片

源代碼和上圖右側的文字來源:http://www.runoob.com/cprogramming/c-variables.html 的文章評論區,對代碼片段增加了一個堆區的內存分配(char *p2),探討堆內存的內存分配規律。

C程序存儲結構