C語言之棧和堆(Stack && Heap)的優(yōu)缺點及其使用區(qū)別

本篇文章主要介紹了什么是棧(Stack) 、什么是堆( Heap),以及棧和堆的優(yōu)缺點,同時介紹了應(yīng)該什么時候使用堆和棧,有需要的朋友可以參考下

一、前言

直到現(xiàn)在,我們已經(jīng)知道了我們?nèi)绾温暶鞒A款愋?,例如int,double,等等,還有復(fù)雜的例如數(shù)組和結(jié)構(gòu)體等。我們聲明他們有各種語言的語法,例如Matlab,Python等等。在C語言中,把這些變量放在棧內(nèi)存中。

二、基礎(chǔ)

1、棧

什么是棧,它是你的電腦內(nèi)存的一個特別區(qū)域,它用來存儲被每一個function(包括mian()方法)創(chuàng)建的臨時變量。棧是FILO,就是先進后出原則的結(jié)構(gòu)體,它密切的被CPU管理和充分利用。每次function聲明一個新的變量,它就會被“推”到棧中。然后每次一個function退出時,所有關(guān)于這個函數(shù)中定義的變量都會被釋放(換句話說就是刪除)。一旦棧中的變量釋放,這塊區(qū)域就會變成可用的,提供給其他棧中的變量。

用棧存儲變量的好處是,內(nèi)存是被你管理的。你不用手動的創(chuàng)建內(nèi)存,不用當你不在需要它的時候手動釋放內(nèi)存。另外,由于CPU組織棧內(nèi)存很高效。讀出和寫入棧變量是很快的。

理解棧的關(guān)鍵是理解概念,當一個function退出時,所有它的變量都會從棧中彈出,以后都會永遠消失。因此棧中的變量本質(zhì)是局部的。這和我們原來理解為變量作用域或者本地或者全局變量是相關(guān)的。在C中,一個公共的bug 是從你程序中的一個function外嘗試訪問一個在棧中的這個function的變量(在該function已經(jīng)退出后)。

關(guān)于棧的另一個特點我們應(yīng)該記住,就是存儲再棧中的變量的大小有限制。而堆上創(chuàng)建變量不用考慮。

總結(jié)棧:

a、棧的生長和伸縮就是函數(shù)壓入或者推出局部變量。

b、我們不用自己去管理內(nèi)存,變量創(chuàng)建和釋放都是自動的。

c、棧中的變量只有在函數(shù)創(chuàng)建運行時存在。

2、 堆

堆也是我們的計算機內(nèi)存中的一個區(qū)域,但是他不是自動管理的。而且也不是被CPU密切的管理著。它是一片更加自由的內(nèi)存區(qū)域(很大)。要想在堆上創(chuàng)建內(nèi)存,我們必須使用malloc() 或者calloc(),他們都是C語言編譯的。一旦你在堆上分配內(nèi)存,當你不在需要的時候你必須用free()去銷毀。如果你不銷毀或者銷毀失敗,你的程序就會有內(nèi)存泄露。換句話說就是堆內(nèi)存會一直在,其他進程無法使用。我們將會再調(diào)試部分看到,那里有一個叫做Valgrind的東西,它可以幫助你發(fā)現(xiàn)內(nèi)存泄露。

不像棧,堆沒有變量大小的限制(除了你電腦的物理限制條件外)。堆內(nèi)存讀出和寫入都比較慢,因為它必須使用指針圖訪問堆內(nèi)存。我們將會下面講解指針。

3、棧和堆的優(yōu)缺點

棧:

a、快速訪問。

b、沒有必要明確的創(chuàng)建分類變量,因為它是自動管理的。

c、空間被CPU高效地管理著,內(nèi)存不會變成碎片。

d、只有局部變量

e、受限于棧大小(取決于操作系統(tǒng))

f、變量不能調(diào)整大小。

堆:

a、變量可以被全局訪問

b、沒有內(nèi)存大小限制

c、(相對)訪問比較慢

d、沒有高效地使用空間,隨著塊內(nèi)存的創(chuàng)建和銷毀,內(nèi)存可能會變成碎片。

e、你必須管理內(nèi)存(變量的創(chuàng)建和銷毀你必須要負責)

f、變量大小可以用realloc( )調(diào)整

例如:

下面是一個在棧上創(chuàng)建變量的短程序。和我們看到的其他程序類似

#include

doublemultiplyByTwo (doubleinput) {

doubletwice = input * 2.0;

returntwice;

}

intmain(intargc,constchar* argv[]) {

intage = 30;

doublesalary = 12345.67;

doublemyList[3] = {1.2,2.3,3.4};

printf("double your salary is %.3f\n",multiplyByTwo(salary));

return0;

}

運行結(jié)果如下:double your salary is 24691.340

在第7,8和9行,我們聲明了三個變量:一個int變量、一個double變量和一個包含三個包含double的數(shù)組。這三個變量在main()函數(shù)創(chuàng)建,被壓入棧中。當main()函數(shù)退出(程序退出),這些變量就會出棧。同樣地,在multiplyByTwo函數(shù)中,第二個double變量,也會在multiplyByTwo()函數(shù)創(chuàng)建的時候壓入棧中。一旦函數(shù)退出,第二個變量就會出棧,永遠地消失。

備注:有一種方法可以告訴C保持一個棧變量。即使它的創(chuàng)建函數(shù)退出。那就是用static關(guān)鍵字當聲明變量的時候。一個變量用static關(guān)鍵之聲明,因此就會變成一個類似與全局變量的東西。但是它僅僅在創(chuàng)建它的函數(shù)里面可見。這是一個奇怪的東西,除非你在一個非常特殊的情況下需要。

下面是另一個版本的創(chuàng)建變量在堆上而不是在棧上:

#include

#include

double*multiplyByTwo (double*input) {

double*twice =malloc(sizeof(double));

*twice = *input *2.0;

returntwice;

}

intmain(intargc,constchar* argv[]) {

int*age =malloc(sizeof(int));

*age = 30;

double*salary =malloc(sizeof(double));

*salary = 12345.67;

double*myList =malloc(3 *sizeof(double));

myList[0] = 1.2;

myList[1] = 3.4;

myList[2] = 4.5;

double*twiceSalary = multiplyByTwo(salary);

printf("double your salary is %.3f\n",*twiceSalary);

free(age);

free(salary);

free(myList);

free(twiceSalary);

return0;

}

正如你所看到的,我們用malloc()去分配堆內(nèi)存,用free()去釋放它。這樣不是很大的處理,但是很笨重。還有一件要注意的事情是:這樣會由很多*號。這些是指針。malloc()(calloc()和free())函數(shù)處理的是指針而不是真正的數(shù)值。我們將會在下邊討論指針。指針在C棧是一個特殊的數(shù)據(jù)類型,它用來存儲內(nèi)存的地址而不是存儲實際的values.因此在

*twice = *input *2.0;

這行,twice變量不是一個double,而是一個指向double的指針,是double被存儲再內(nèi)存中的地址。

4、什么時候使用堆

我們應(yīng)該什么時候使用堆和棧呢?如果我們需要分配一大塊內(nèi)存(例如一個很大的數(shù)組或者一個很大的結(jié)構(gòu)體),而且我們需要保持這個變量很長時間(例如全局變

量)。我們應(yīng)該分配堆內(nèi)存。如果你處理的很小的變量,而且只要再函數(shù)使用的時候存活,那么你應(yīng)該使用棧,它比較方便而且快捷。如果你需要類似與數(shù)組或者結(jié)

構(gòu)體的變量,而且能夠動態(tài)改變大?。ɡ缫粋€數(shù)組可以根據(jù)需要添加數(shù)據(jù)或者刪除數(shù)據(jù)),那么你可以用malloc(),realloc()給他們分配堆內(nèi)

存,用free()手動的管理內(nèi)存。當我們討論完指針,我們將會討論動態(tài)分配數(shù)據(jù)結(jié)構(gòu)體。

通過以上對棧和堆的介紹,希望對大家了解和區(qū)分棧和堆有所幫助。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • JVM內(nèi)存模型Java虛擬機(Java Virtual Machine=JVM)的內(nèi)存空間分為五個部分,分別是: ...
    光劍書架上的書閱讀 2,775評論 2 26
  • 一、前言直到現(xiàn)在,我們已經(jīng)知道了我們?nèi)绾温暶鞒A款愋?,例如int,double,等等,還有復(fù)雜的例如數(shù)組和結(jié)構(gòu)體等...
    我不是掌柜閱讀 656評論 0 0
  • C語言中內(nèi)存分配 在任何程序設(shè)計環(huán)境及語言中,內(nèi)存管理都十分重要。在目前的計算機系統(tǒng)或嵌入式系統(tǒng)中,內(nèi)存資源仍然是...
    一生信仰閱讀 1,312評論 0 2
  • 小時候媽媽總是說她的18歲特別美好,那時候媽媽還是一個小美女,喜歡她的男生很多,媽媽說她的18歲,在悶熱的教室中卻...
    youaremySummer閱讀 256評論 0 0
  • 小朱一到家就跟我說,媽媽我給你和爸爸寫了一封信,這次寫的很好,拿到我眼前給我看,兒子真是太有心了,心里寫到媽媽我愛...
    TianHao媽媽閱讀 181評論 0 0

友情鏈接更多精彩內(nèi)容