內(nèi)存四區(qū)
1棧區(qū)
由編譯器自動分配釋放 坟漱,存放函數(shù)的參數(shù)值铺遂,局部變量的值等
2.堆區(qū)
一般由程序員分配釋放胳嘲, 若程序員不釋放甚带,程序結(jié)束時可能由OS回
3.靜態(tài)全局數(shù)據(jù)區(qū)
主要包括靜態(tài)全局區(qū)和常量區(qū)
- char *s = "HelloWorld";//該字符串 HelloWorld 即存放于文字常量區(qū)温算,不可修改怜校。但指針s存放于棧區(qū)。
若在程序中嘗試對其修改(例如嘗試修改第一個字符 *s = 'h';)注竿,將出現(xiàn)編譯可通過茄茁,運行報錯的情況。
- 同時因注意它與const修飾的變量之間的區(qū)別:
char aa = 'A';//aa存放于棧區(qū)
const char bb = 'B'; //bb同樣存放于棧區(qū)
const修飾的變量僅僅用于告訴編譯器bb是一個常量巩割,如果后續(xù)的程序中有出現(xiàn)嘗試修改bb的操作時裙顽,編譯將報錯。
這種寫法主要是為了防止程序員在后續(xù)的代碼中誤操作bb變量而添加的一個約束條件宣谈,并不會影響它存放的位置愈犹。
4.代碼區(qū)
存放函數(shù)體的二進制代碼。用于存儲程序編譯連接后生成的二進制機器碼指令的內(nèi)存區(qū)域
區(qū)別
-
能否產(chǎn)生碎片
對于堆來講闻丑,頻繁的new/delete勢必會造成內(nèi)存空間的不連續(xù)漩怎,從而造成大量的碎片,使程序效率降低嗦嗡。對于棧來講勋锤,則不會存在這個問題。 -
生長方向不同
對于堆來講侥祭,生長方向是向上的怪得,也就是向著內(nèi)存地址增加的方向;對于棧來講卑硫,它的生長方式是向下的徒恋,是向著內(nèi)存地址減小的方向增長。 -
分配方式不同
堆都是動態(tài)分配的欢伏;棧有靜態(tài)和動態(tài)兩種分配方式入挣。靜態(tài)分配由編譯器完成,比如局部變量的分配硝拧。動態(tài)分配由alloca函數(shù)進行径筏、但棧的動態(tài)分配和堆是不同的,它的動態(tài)分配由編譯器進行釋放障陶,無需我們手工實現(xiàn)滋恬。 -
分配效率不同
棧是機器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu),計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址抱究,壓棧出棧都有專門的指令執(zhí)行恢氯,這就決定了棧的效率比較高。堆則是c/c++庫函數(shù)提供的,機制很復雜勋拟。庫函數(shù)會按照一定的算法進行分配勋磕。顯然,堆的效率比棧要低得多敢靡。 -
Buf的生長方向
如數(shù)組生長方向都是由低地址到高地址生長挂滓,和棧的生長方向無關(guān)
實驗
代碼
int add(int x, int y);
int sub(int x, int y);
int main() {
int c = 30;
int d[10];
int *p=malloc(sizeof(int)*2);
int *p1=malloc(sizeof(int));
printf("-----static--------\n");
printf("%x\n", &a);
printf("%x\n", &b);
printf("------stack-------\n");
printf("%x\n", &c);
printf("%x\n", &d);
printf("%x\n", &p);
printf("%x\n", &p1);
add(a,b);
sub(b,c);
printf("------heap-------\n");
printf("%x\n", p);
printf("%x\n", p1);
printf("------code-------\n");
printf("%x\n", add);
printf("%x\n", sub);
}
int add(int x, int y) {
printf("%x\n", &x);
printf("%x\n", &y);
return x + y;
}
int sub(int x, int y) {
printf("%x\n", &x);
printf("%x\n", &y);
return x - y;
}
結(jié)果
-----static--------
405008
40500c
------stack-------
28ff3c
28ff14
28ff10
28ff0c
28fef0
28fef4
28fef0
28fef4
------heap-------
4629f0
462a00
------code-------
401933
401969
- 棧地址的增長方向是由高->低
- 堆地址的增長方向是由低->高
- 靜態(tài)全局數(shù)據(jù)區(qū)的增長方向是由低->高