------------------- 數組
| 程序棧 |----------高地址--〉低地址函數
-------------------spa
| 堆 |----------向上增加指針
-------------------進程
| BSS |----------數據段ip
| 全局和靜態變量 |內存
------------------- ----------低地址字符串
| 可執行代碼 |----------代碼段terminal
-------------------class
可執行指令放在代碼段中,任什麼時候刻,內存中只有一份相同程序的指令拷貝,多個實例共享這些代碼。
初始化爲非零的靜態數據和全局數據存放在數據段中,運行相同程序的每一個進程,有本身的數據段。
初始化爲零的全局數據和靜態分配數據存放在進程的BSS區域中,每一個運行的進程都有本身的BSS,程序運行的時候,將數據放到數據段中,由此可知,只有初 始化爲非零的變量才佔用空間,因此對於相似static int ss[1024];這樣的數組自動用0來填充,它佔的空間很小。
堆,動態內存來自於堆,即:經過malloc獲得的空間,一般狀況下,堆是向上增加的,即:後面分配的地址比前面的地址在數值上大一些。
棧,分配本地變量的地方,函數參數、函數的返回值和返回地址也放在棧空間中,須要特別注意的是,當函數返回後,存儲在棧空間中的函數變量「自動消失」,空間被其餘函數使用。棧空間是向下增加的。
在C語言中,通常經過malloc/calloc函數分配空間,經過free()函數釋放空間,使用realloc()改變已分配空間的大小。
分配內存的步驟:
1.申明一個指定類型的指針
2.計算要分配空間的大小,通常使用函數sizeof()來實現
3.調用函數malloc()完成空間的申請,將函數的返回值賦給指針變量,
4.檢查返回值是否不爲NULL,保證空間分配成功
5.分配好的空間是沒有通過初始化的,其中可能包含一些垃圾信息,所以
調用函數memset()將其用0來填充是個好的習慣
釋放內存步驟:
1.調用函數free()釋放掉空間
注意:1.不可使用free()掉後的空間
2.free()後,最好將指針置爲NULL,由於若是不作這步處理,
原來的指針依舊指向剛纔釋放的空間,能夠繼續操做
3.避免重複釋放空間
在Unix系統上,提供了函數alloca()函數,能夠實如今棧空間上分配指定大小的空間,這樣的好處是,函數結束後,空間自動釋放,沒必要顯式地調用函數free(),可是該函數有不少弊端,好比不可移植等,所以不建議使用。
有必要提一下malloc、calloc、realloc函數的底層實現,在Linux系統中,提供了brk()和sbrk()函數,上面幾個函數就是在這兩個函數的基礎上實現的。
int *p = (int*)malloc(20);//動態在堆區分配空間,(空間內容初始值爲隨機值)必須人爲釋放
//free(p);;
int *p2 = (int*)alloca(20);//動態在棧區分配空間(空間內容初始值爲隨機值),自動釋放。
int *p3 = (int *)calloc(4,5);//動態在堆區分配空間,(空間內容初始值爲0)必須人爲釋放
free(p3); p3 = NULL;
int *p4 = (int*)realloc(p,30);////動態在堆區擴充內存空間,(空間內容初始值爲隨機值)必須人爲釋放
free(p4); p4 = NULL;
char *p5 = "hello";
char *p6 = "hello";
*p5 == *p6 由於 "hello" 是字符串常量,定義後會在常量去開闢一塊空間存儲hello,
由於是在常量區不可修改,因此不必再重新申請一塊新空間去存儲另外一個"hello",因此,
p5,p6指的是一塊區域.
char p7[] = "hello";
char p8[] = "hello";
就徹底不同了,由於這是在棧區申請的區域,因此是不一樣的兩塊空間.