C語言內存分配淺析


本文主要通過一個測試程序,來觀察全局變量、靜態變量、局部變量、常量、子函數、函數參數等,它們在內存中的分布。最后列舉了內存中的幾種空間類型。希望對大家有所幫助。
 

測試程序

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 void fun(int i);
 5 
 6 int global_i = 100;
 7 int global_j = 200;
 8 int global_k,global_h;
 9 char *global_p;
10 int main()
11 {
12     static int static_i = 5;
13     static int static_j = 10;
14     static int static_k;
15     static int static_h;
16 
17     printf("\n全局數據地址(有初值):\n");
18     printf("global_i\t 0x%p = %d\n", &global_i, global_i);
19     printf("global_j\t 0x%p = %d\n", &global_j, global_j);
20     printf("靜態數據地址(有初值):\n");
21     printf("static_i\t 0x%p = %d\n", &static_i, static_i);
22     printf("static_j\t 0x%p = %d\n", &static_j, static_j);
23 
24     printf("\n全局數據地址(無初值):\n");
25     printf("global_k\t 0x%p = %d\n", &global_k, global_k);
26     printf("global_h\t 0x%p = %d\n", &global_h, global_h);
27     printf("靜態數據地址(無初值):\n");
28     printf("static_k\t 0x%p = %d\n", &static_k, static_k);
29     printf("static_h\t 0x%p = %d\n", &static_h, static_h);
30 
31     char *pstr1 = "Mr.Shao";
32     char *pstr2 = "Hello";
33     char *pstr3 = "Mr.Shao";
34     printf("\n字符串常量數據地址:\n");
35     printf("*pstr1\t 0x%p\n",  pstr1);
36     printf("*pstr3\t 0x%p\n", pstr3);
37     printf("*pstr2\t 0x%p\n", pstr2);
38 
39     int i = 5;
40     int j = 10;
41     int f, h;
42     char c='a';
43     char s[] = "abc";
44     char *p2=NULL;
45     char *p3 = "abc"; //"123456/0"在常量區,p3在棧上。
46     printf("\n棧中數據地址=有初值:\n");
47     printf("i\t 0x%p = %d\n",&i,i);
48     printf("j\t 0x%p = %d\n", &j, j);
49     printf("f\t 0x%p = %d\n", &f, f);
50     printf("h\t 0x%p = %d\n", &h, h);
51     printf("c\t 0x%p = %d\n", &c, c);
52     printf("s\t 0x%p = 0x%p\n", &s, s);
53     printf("p2\t 0x%p = 0x%p\n", &p2, p2);
54     printf("p3\t 0x%p = 0x%p\n", &p3, p3);
55 
56     const int NUM = 2;
57     int *p = (int*)malloc(NUM * sizeof(int));
58     global_p = (char *)malloc(10);
59     p2 = (char *)malloc(20);
60     printf("NUM\t 0x%p = 0x%d\n", &NUM, NUM);
61     printf("p\t 0x%p = 0x%p\n", &p, p);
62     printf("\n堆中數據地址\n");
63     printf("*p\t 0x%p\n", p);
64     printf("*global_p\t 0x%p\n", global_p);
65     printf("*p2\t 0x%p\n", p2);
66 
67 
68     printf("\n子函數的地址\n");
69     printf("void fun(int)\t 0x%p\n", fun);
70     fun(47);//子函數
71 
72     free(p);
73     free(global_p);
74     free(p2);
75     return 0;
76 }
77 
78 void fun(int i)
79 {
80     int j = i;
81     static int static_i = 100;
82     static int static_j;
83 
84     printf("\n子函數:\n");
85     printf("棧中數據地址(參數)\n");
86     printf("i\t 0x%p = %d\n", &i, i);
87     printf("棧中數據地址j\n");
88     printf("j\t 0x%p = %d\n", &j, j);
89     printf("靜態數據地址(有初值)\n");
90     printf("static_i\t 0x%p = %d\n", &static_i, static_i);
91     printf("靜態數據地址(無初值)\n");
92     printf("static_j\t 0x%p = %d\n", &static_j, static_j);
93 }

輸出:

 

實驗總結

  1. 變量在內存地址的分布(由大到小):(堆中變量的地址不固定)全局\靜態(未初始化)、常量數據、全局\靜態(初始化)、代碼區、棧
  2. 棧中的變量按聲明的順序在內存的中依次,地址由大到小。證明了棧的伸展方向是由高地址向低地址擴展的
  3. 棧中的變量:主/子函數內聲明的非靜態變量(包括數組變量、指針變量、const變量);函數的參數變量。
  4. (除了棧)同一區域的各變量按聲明的順序在內存的中依次,地址由大到小。
  5. 全局變量和靜態變量如果不賦值,默認為0; 棧中的變量如果不賦值,則是一個隨機的數據。
  6. 全局變量和(主/子函數內的)靜態變量是等同的,已初始化的全局變量和靜態變量分配在一起,未初始化的全局變量和靜態變量分配在另一起。
  7. 主函數中棧的地址都要高於子函數中參數及棧地址。

 

程序的內存空間 
1、棧區(stack)
      程序運行時由編譯器自動分配,存放局部變量、函數參數、返回數據等。其操作方式類似於數據結構中的棧。程序結束時由編譯器自動釋放。棧內存分配運算內置於處理器的指令集中,效率很高,但是分配的內存容量有限。
2、堆區(heap)
     從堆上分配稱動態內存分配。程序在運行的時候用malloc或new申請任意多少的內存,分配方式類似於鏈表。程序員自己負責在何時用free或delete釋 放內存。
     動態內存的生存期由程序員決定,使用非常靈活,但如果在堆上分配了空間,就有責任回收它,否則運行的程序會出現內存泄漏,頻繁地分配和釋放不同大 小的堆空間將會產生堆內碎塊。
3、全局區(靜態區)(static)
     內存在程序編譯的時候就已經分配好。全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。 - 程序結束后由系統釋放
4、文字常量區 
     常量字符串就是放在這里的。 程序結束后由系統釋放
5、程序代碼區
     存放函數體(類成員函數和全局函數)的二進制代碼。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM