程序的靜態存儲區,動態存儲區和堆以及棧的關係是什麼?

換句話說,堆是位於靜態存儲區?棧是位於動態存儲區?

這一塊太讓我糊塗了,望高手指點一下


謝邀。堆不是在靜態存儲區的,是屬於動態存儲區的。

所謂靜態,就是一定會存在的而且會永恆存在、不會消失,這樣的數據包括常量、常變數(const 變數)、靜態變數、全局變數等。

動態的話,就是會變化的了。動態的區域,就是堆和棧。這個棧應該稱作 call stack,上面會存放函數的返回地址、參數和局部變數。而堆放就是我們通過 new 算符和 malloc 函數分配得到的空間。

這些段在內存中分配位置,跟硬體架構和操作系統都有關係,x86中棧都是由高地址向低地址分配,堆是由低地址向高地址分配,不過在 Windows 和 Linux 中堆和棧的位置相反,另外存放靜態數據、代碼的區域位置也有一些不同(我是在《C和C++安全編碼》上看到的,具體細節記不清了,現在不在學校,網上搜了好久也沒有見到圖,所以就不貼圖了)。

另外,棧是屬於線程的,每一個線程會有一個自己的棧。

不知道講明白了沒有,歡迎留言討論。

相關資料:

Windows中數據內存的限制,有解釋靜態數據、動態數據和棧: http://software.intel.com/en-us/articles/memory-limits-applications-windows/

文章《Memory management in C: The heap and the stack》: http://www.inf.udec.cl/~leo/teoX.pdf

http://en.wikipedia.org/wiki/C_dynamic_memory_allocation


Google一下「堆和棧的區別」, 十有八九你會讀到這篇文章,由於被轉載太多,我也沒法找到誰先寫的,隨便貼了一個博客鏈接。至少可以明確地告訴你,堆和棧都是在動態存儲區的,至於哪些在靜態存儲區,文章也有提及。

上面鏈接的博文已經很好了,我結合這個自己做了一些實驗:

char stack_addr = "a";
char *a = "1234";
char *b;
b = (char *)malloc(5);
b[0] = "1"; b[1] = "2"; b[2] = "3"; b[3] = "4";
char c[] = "1234";

printf("%x
", (int)stack_addr);
printf("%x %x
", (int)a, (int)a[0]);
printf("%x %x
", (int)b, (int)b[0]);
printf("%x %x
", (int)c, (int)c[0]);

我們默認認為變數stack_addr在棧中,臨近的地址在同一個結構中。

一次運行的結果如下:

bfe6b846

bfe6b83c 8048600

bfe6b840 9829008

bfe6b847 bfe6b847

如文章所說,a,b,c對應的指針其實都在stack中,但是給他們賦值的量卻截然不同,a的字元串是字面值常量,在常量區; b分配的內存空間在堆上,c的元素則都在棧上。

大體上就是這樣,堆和棧的其他特性你可以在文章中看到,我寫的一篇博文Heap and Stack (堆和棧)也談了自己的一些其他理解,可能有錯,歡迎指正。


棧和堆屬於動態存儲區

要回答這個問題,首先說明一下三種變數

1.靜態 常量 全局 變數

2.局部自動變數

3.動態變數

第一種變數就是存放在靜態存儲區,他們在程序編譯完成後就已經分配好了,生命周期持續至程序結束。

第二種是變數是存放在棧區 在棧區裡面其實又可以分成好幾個區域,他們叫做棧楨,一個棧楨就是一個函數,需要調用該函數的時候就如入棧,函數return的時候就會彈出棧,所以他們的生命周期是從函數的開始直到函數結束。而棧幀裡面又存放著什麼呢,棧幀存放著以下幾種東西:參數變數的地址,局部變數的地址,return的地址(還有棧指針和基指針,想知道這個是就什麼百度吧)

深入理解C指針讀書筆記(程序的棧和堆)

我的博客這裡有具體介紹棧

第三種變數通常是由malloc new等分配的空間,生命周期是從分配的那一刻直到free結束。


推薦閱讀:

為什麼很多編程語言採用花括弧區分 block 而非縮進?
為什麼說 C 語言是系統級編程的首選?
Linux 下有沒有像 Visual Studio 一樣的,有自動填充、提示語法錯誤、斷點調試等功能的 C/C++ IDE?
用 int 類型表示多個字母,把多個字母轉化為整數的原理是什麼?
為什麼說C++不是C的超集?

TAG:編程語言 | 編程 | C編程語言 | C | CC |