C與C++的進程空間化成了好多的區間,這些區間存儲的內容並不同。下面利用代碼進行解析。
上圖是進程空間的結構。
(注):很多書上講到堆是向上增,棧是向下降。這種說話很不明確,因爲不同的書上有不同的畫法。準確的說是堆向高地址增長,棧向低地址增長。
一段C或C++的代碼,具體的變量到底怎麼存儲如下:
#include<stdio.h>
#include<malloc.h>
int a = 1;//已初始化數據全局變量
int b;//未初始化數據
void main()
{
int b; //局部變量,注意,只是局部變量,因爲在函數中定義。存在棧中。
char[] = "abc"; //局部變量 存在棧中。
char *p1; //局部指針變量,存在棧中。
char *p2 = "12345"; //12345屬於常量,在常量區內存儲。其中常量屬於已初始化數據,在data去,因爲常量可以賦給任何變量。
static int C = 0;//靜態變量,在已初始化區
p1 = (char*)malloc(sizeof(char));
p2 = (int*)malloc(sizeof(int));
//上面變量p1與p2在棧中,利用malloc申請的區域在堆中
free(p1);
free(p2);
//free函數會清除掉堆中的函數。
}
(一),入棧與出棧
棧的利用系統都會自動完成順序也很明確,當從main函數入口時。局部變量依次入棧,函數調用結束再依次出棧,因此順序很明確。
(二),堆空間的使用
(1),爲何要用堆的空間,先看下面的例子:讀入一個含n個整數的數組。代碼如下:
#include"csapp.h"
#define MAIX 100
int array[MAIX];// 此數組存在初始化區;
int main()
{
int i n;
scanf("%d",&n);
if (n > MAIX)
{
app_error("too big");
}
for(i = 0;i < n;i++)
{
scanf("%d",&array[i]);
}
exit(0);
}
上面的代碼沒有任何的毛病,但問題在維護上。因爲只能接受100大小的數組,大的話會報錯,當然可以把數組設的很大,但是會造成內存的浪費和維護的麻煩。甚至來說,如果數組太大,會造成內存泄露。
(2),堆的好處
上面的代碼存在初始化數據區顯然不合適,這就引出堆的好處,要多少內存給多少,並且能夠及時回收。
#include"csapp.h"
int main()
{
int i n *array; //array這個指針在棧裏存着
scanf("%d",&n);
array = (int*)malloc(n*sizeof(int));//array指針指向堆區的一個地址,大小爲自己申請。
for(i = 0;i < n;i++)
{
scanf("%d",&array[i]);
}
free(array);//不會造成內存浪費
exit(0);
}
注:(1)向堆申請內存的方式在C++的實例化對象的部分會更爲顯著。
(2)堆棧的用法與細節比這要更爲的複雜,此文章只是簡要的概述大致過程。
(3)希望有理解錯的地方各位及時指正,謝謝。