當前位置:首頁 » 編程語言 » c語言堆的特點
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

c語言堆的特點

發布時間: 2022-09-21 19:57:39

『壹』 c語言堆和棧,靜態區的理解

樓主問這樣的問題,需要澄清平台。比如windows下的與linux下的編譯器及很多嵌入式C編譯器不同。為什麼考慮嵌入式C?原因是目前C語言的很大市場在嵌入式領域。windows下,除了某些特殊需要,java,C++,C#已經優勢盡顯了。

另外,討論了半天,q在你代碼的那裡?我怎麼沒找到??我眼睛都揉紅了也沒找見呀
只好表述一下原理
VC下:
1. 函數形參和函數內部非靜態局部變數都在棧上分配(所以a,b,p本身都在棧上。但p指向的內容在堆上。q在哪裡,我找不到)。
棧的分配的方法是:sp-=字數。
sp是堆棧指針。」字數「是說:你分配一個位元組的局部變數,編譯器也給你一個字的長度的空間。原因是,堆棧是具有字長度的。16位、32位機器下,字長度為16,64位機器下,字長度為32.
而且,windows下,棧是從高地址向低地址增長的。為什麼?棧與堆共享空間,並且,堆從低向高長,棧從高向低長,降低溢出風險。

靜態區名字本身就說明了他的特性:靜止的,不隨程序的運行變化。也就是相對的說,堆和棧都是動態的。靜態區是編譯器在編譯時指定長度、鏈接時定位地址、windows載入器載入時分配內存。
這里的動與靜是編譯器和鏈接器的說法,是語言層面。不適用於系統層面。Windows隨時可能將任何用戶程序程序的全部資源「請出」內存,也可重新載入,此時,什麼靜都是浮雲。

還有返回值。樓主的main不返回值編譯器會警告你的。返回值存在什麼地方?
答案是寄存器里AX(EAX,DX,EDX等)。

嵌入式系統里可能這些都不適用。比如,某些嵌入式處理器的形參直接使用寄存器(R0~R15,或A、B等)

『貳』 C語言中內存堆和棧的區別

堆(heap)和棧(stack)原本是兩種不同的數據結構,在C語言內存表述中,代表著用這兩種數據結構管理的兩種內存塊。
堆由整個系統共享,各個進程擁有同一個堆。 棧由每個進程自行管理,也就是每個進程的棧是獨立的,互不相關。
具體區別如下:
一、棧上的內存由系統自動管理分配,用於存儲局部變數。 堆中的內存由編程人員主動申請,在C語言中申請內存的函數為malloc, 使用後需要編程人員自行調用free函數釋放。
二、從分配釋放及訪問速度上,棧內存的存取,申請釋放速度要高於堆內存。
三、棧內存相對於堆內存要小的多,所以在編程的時候,一般不建議使用占空間過大的局部變數。
四、堆中所有數據均由編程人員申請使用。 棧中除了存放函數中可見的局部變數外,還有各種系統環境數據。

『叄』 C語言中內存堆和棧的區別

C語言中內存堆和棧的區別

在計算機領域,堆棧是一個不容忽視的概念,我們編寫的C語言程序基本上都要用到。但對於很多的初學著來說,堆棧是一個很模糊的概念。

堆棧:一種數據結構、一個在程序運行時用於存放的地方,這可能是很多初學者的認識,因為我曾經就是這么想的和匯編語言中的堆棧一詞混為一談。我身邊的一些編程的朋友以及在網上看帖遇到的朋友中有好多也說不清堆棧,所以我想有必要給大家分享一下我對堆棧的看法,有說的不對的地方請朋友們不吝賜教,這對於大家學習會有很大幫助。

數據結構的棧和堆

首先在數據結構上要知道堆棧,盡管我們這么稱呼它,但實際上堆棧是兩種數據結構:堆和棧。

堆和棧都是一種數據項按序排列的數據結構。

棧就像裝數據的桶或箱子

我們先從大家比較熟悉的棧說起吧,它是一種具有後進先出性質的數據結構,也就是說後存放的先取,先存放的後取。

這就如同我們要取出放在箱子裡面底下的東西(放入的比較早的物體),我們首先要移開壓在它上面的物體(放入的比較晚的物體)。

堆像一棵倒過來的樹

而堆就不同了,堆是一種經過排序的樹形數據結構,每個結點都有一個值。
通常我們所說的堆的數據結構,是指二叉堆。
堆的特點是根結點的值最小(或最大),且根結點的兩個子樹也是一個堆。
由於堆的這個特性,常用來實現優先隊列,堆的存取是隨意,這就如同我們在圖書館的書架上取書,雖然書的擺放是有順序的,但是我們想取任意一本時不必像棧一樣,先取出前面所有的書,書架這種機制不同於箱子,我們可以直接取出我們想要的書。

內存分配中的棧和堆

然而我要說的重點並不在這,我要說的堆和棧並不是數據結構的堆和棧,之所以要說數據結構的堆和棧是為了和後面我要說的堆區和棧區區別開來,請大家一定要注意。

下面就說說C語言程序內存分配中的堆和棧,這里有必要把內存分配也提一下,大家不要嫌我啰嗦,一般情況下程序存放在Rom(只讀內存,比如硬碟)或Flash中,運行時需要拷到RAM(隨機存儲器RAM)中執行,RAM會分別存儲不同的信息,如下圖所示:

內存中的棧區處於相對較高的地址以地址的增長方向為上的話,棧地址是向下增長的。

棧中分配局部變數空間,堆區是向上增長的用於分配程序員申請的內存空間。另外還有靜態區是分配靜態變數,全局變數空間的;只讀區是分配常量和程序代碼空間的;以及其他一些分區。

來看一個網上很流行的經典例子:

main.cpp

1 int a = 0; //全局初始化區
2 char *p1; //全局未初始化區
3 main()
4 {
5 int b; //棧
6 char s[] = "abc"; //棧
7 char *p2; //棧
8 char *p3 = "123456"; //123456\0在常量區,p3在棧上。
9 static int c =0; //全局(靜態)初始化區
10 p1 = (char *)malloc(10); //堆
11 p2 = (char *)malloc(20); //堆
12 }
復制代碼

0.申請方式和回收方式不同

不知道你是否有點明白了。

堆和棧的第一個區別就是申請方式不同:棧(英文名稱是stack)是系統自動分配空間的,例如我們定義一個 char a;系統會自動在棧上為其開辟空間。而堆(英文名稱是heap)則是程序員根據需要自己申請的空間,例如malloc(10);開辟十個位元組的空間。

由於棧上的空間是自動分配自動回收的,所以棧上的數據的生存周期只是在函數的運行過程中,運行後就釋放掉,不可以再訪問。而堆上的數據只要程序員不釋放空間,就一直可以訪問到,不過缺點是一旦忘記釋放會造成內存泄露。還有其他的一些區別我認為網上的朋友總結的不錯這里轉述一下:

1.申請後系統的響應

棧:只要棧的剩餘空間大於所申請空間,系統將為程序提供內存,否則將報異常提示棧溢出。

堆:首先應該知道操作系統有一個記錄空閑內存地址的鏈表,當系統收到程序的申請時,會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,然後將該結點從空閑結點鏈表中刪除,並將該結點的空間分配給程序,另外,對於大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的 delete語句才能正確的釋放本內存空間。另外,由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多餘的那部分重新放入空閑鏈表中。

也就是說堆會在申請後還要做一些後續的工作這就會引出申請效率的問題。

2.申請效率的比較

根據第0點和第1點可知。

棧:由系統自動分配,速度較快。但程序員是無法控制的。

堆:是由new分配的內存,一般速度比較慢,而且容易產生內存碎片,不過用起來最方便。

3.申請大小的限制

棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,在 WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數),如果申請的空間超過棧的剩餘空間時,將提示overflow。因此,能從棧獲得的空間較小。

堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲的空閑內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。

4.堆和棧中的存儲內容

由於棧的大小有限,所以用子函數還是有物理意義的,而不僅僅是邏輯意義。

棧: 在函數調用時,第一個進棧的是主函數中函數調用後的下一條指令(函數調用語句的下一條可執行語句)的地址,然後是函數的各個參數,在大多數的C編譯器中,參數是由右往左入棧的,然後是函數中的局部變數。注意靜態變數是不入棧的。
當本次函數調用結束後,局部變數先出棧,然後是參數,最後棧頂指針指向最開始存的地址,也就是主函數中的下一條指令,程序由該點繼續運行。

堆:一般是在堆的頭部用一個位元組存放堆的大小。堆中的具體內容有程序員安排。

5.存取效率的比較

char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
復制代碼
aaaaaaaaaaa是在運行時刻賦值的;放在棧中。
而bbbbbbbbbbb是在編譯時就確定的;放在堆中。
但是,在以後的存取中,在棧上的數組比指針所指向的字元串(例如堆)快。

比如:

#include
void main()
{
char a = 1;
char c[] = "1234567890";
char *p ="1234567890";
a = c[1];
a = p[1];
return;
}
復制代碼

對應的匯編代碼
10: a = c[1];
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]
0040106A 88 4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov al,byte ptr [edx+1]
00401073 88 45 FC mov byte ptr [ebp-4],al

關於堆和棧區別的比喻

堆和棧的區別可以引用一位前輩的比喻來看出:

使用棧就象我們去飯館里吃飯,只管點菜(發出申請)、付錢、和吃(使用),吃飽了就走,不必理會切菜、洗菜等准備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。

使用堆就象是自己動手做喜歡吃的菜餚,比較麻煩,但是比較符合自己的口味,而且自由度大。比喻很形象,說的很通俗易懂,不知道你是否有點收獲。

『肆』 C與C++中堆是什麼

我們說的堆(heap) 是程序員申請的內存空間,在C/C++中,你可以理解為:所有非常量的指針空間。和heap對應的,還有棧(stack)、靜態區(static)、常量區(const),以及程序代碼區。這些都是程序運行所需要申請的內存空間。

heap堆和其它內存區的主要差別,一個是heap是由程序員申請、釋放和管理的(而不是由系統和程序自動分配和釋放),是動態的;另外一個就是,其它區域都是有固定大小的,而heap的大小,僅僅受到內存和虛擬內存大小的限制,也就是說,理論上你可以申請的堆空間是無限大的。

例子:main(){constchar*m="123";//"123"常量區,m在棧(指針的本身都在棧,下同)chars[]="abc";//常量區char*p3="123456";//常量區staticintc=0;//全局(靜態)初始化區char*p1,*p2;p1=(char*)malloc(10);//分配得來得10位元組的區域就在堆區。p2=newchar[20];//分配得來得20位元組的區域就在堆區。

『伍』 c語言堆和棧的區別

內存分配中的堆和棧

在 C 語言中,內存分配方式不外乎有如下三種形式:

  • 從靜態存儲區域分配:它是由編譯器自動分配和釋放的,即內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在,直到整個程序運行結束時才被釋放,如全局變數與 static 變數。

  • 在棧上分配:它同樣也是由編譯器自動分配和釋放的,即在執行函數時,函數內局部變數的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元將被自動釋放。需要注意的是,棧內存分配運算內置於處理器的指令集中,它的運行效率一般很高,但是分配的內存容量有限。

  • 從堆上分配:也被稱為動態內存分配,它是由程序員手動完成申請和釋放的。即程序在運行的時候由程序員使用內存分配函數(如 malloc 函數)來申請任意多少的內存,使用完之後再由程序員自己負責使用內存釋放函數(如 free 函數)來釋放內存。也就是說,動態內存的整個生存期是由程序員自己決定的,使用非常靈活。需要注意的是,如果在堆上分配了內存空間,就必須及時釋放它,否則將會導致運行的程序出現內存泄漏等錯誤。

數據結構的堆和棧

在數據結構中,棧是一種可以實現「先進後出」(或者稱為「後進先出」)的存儲結構。假設給定棧 S=(a0,a1,…,an-1),則稱 a0為棧底,an-1為棧頂。進棧則按照 a0,a1,…,an-1的順序進行進棧;而出棧的順序則需要反過來,按照「後存放的先取,先存放的後取」的原則進行,則 an-1先退出棧,然後 an-2才能夠退出,最後再退出 a0。

在實際編程中,可以通過兩種方式來實現:使用數組的形式來實現棧,這種棧也稱為靜態棧;使用鏈表的形式來實現棧,這種棧也稱為動態棧。

相對於棧的「先進後出」特性,堆則是一種經過排序的樹形數據結構,常用來實現優先隊列等。假設有一個集合 K={k0,k1,…,kn-1},把它的所有元素按完全二叉樹的順序存放在一個數組中,並且滿足:



則稱這個集合 K 為最小堆(或者最大堆)。

由此可見,堆是一種特殊的完全二叉樹。其中,節點是從左到右填滿的,並且最後一層的樹葉都在最左邊(即如果一個節點沒有左兒子,那麼它一定沒有右兒子);每個節點的值都小於(或者都大於)其子節點的值。

『陸』 c語言中堆和棧的區別詳細解答

棧是先入後出、後入先出的存儲區域,對操作系統來說管理比較簡單,只需要記錄棧底和當前棧頂的位置即可,一般用於保護現場。比如調用函數時,調用點pc地址被壓入堆棧、函數參數被壓入棧,在函數調用結束時會被彈出堆棧指令丟棄或被返回語句利用。
堆是提供給當前程序運行時刻開設緩沖區(如使用malloc函數、new等),由應用程序主動管理(釋放用free和delete),比如printf語句就需要利用堆來臨時保存輸出信息。另外由子程序中開設的非靜態變數一般存放在堆中,退出子程序後被自動釋放。

『柒』 c語言中 堆怎麼理解

c中代碼在代碼段,數據在數琚段,局部變數在堆棧中,除了這些已經明確安排好的空間,剩餘空間稱為自由空間,要利用這些空間可以通過內存分配函數,動態分配,這部分空間稱為堆空間!堆空間相比棧空間是非常大的,棧空間是非常有限的windows下32位程序,預設約為1M而每個程序的地址空間為4G,堆空間使用1~2G內存是不成問題的。
至於p那個指針本身是局部變數,p所指內存在堆上出了函數也是可以用的,必須能夠傳遞出去才行,p自己只能在函數內部使用!傳遞出去的指針必須在適當的時候釋放,否則會產生內存泄漏!
1)這么理解似平不是問題,不過太膚淺;
2)由於各種編程語言(包括c,c )不能(也不允許)直接訪問內存,和cpu各寄存器,要通過標志符(就是一個名字)來訪問它們,這就牽扯到名字的作用域問題了!而內存,寄存器這些東西本來就在和語言無關,只和該語言如何使用有關,通過名字,我們可以更清晰的理解代碼的意圖,可以更好的安排代碼,所以各種語言,通過名字來使用內存和寄存器!這樣名字就和內存,寄存器這種實際存在的東西聯繫到一起了!變數是最經常使用的一種名字了!對c,這種語言自動變數在堆上,只有函數內部甚至內部的一對大括弧內可用(即變數名可見,如果變數的相關內容,如變數值,變數地址,傳遞出去,外部也是可以使用的,當然同一程序的內部變數地址就不要傳遞了!同樣參數和返回值也不要把自動變數地址傳遞出去,因為已經過期,有可能被別的東西佔用了,使用會么錯的,而動態分配的內存其實屬於全局性質的,傳遞出去是沒問題的,只要能夠及時釋放就行,那就是無名全局數據,可以通過有名變數(指針)來使用,因為沒有名字所以不能直接促使用,因為是全局的所以可以任意傳遞,因為要管理的,所以用完要釋放!因為無名,所以只能間接引用!

『捌』 淺析C語言中堆和棧的區別

一、堆棧空間分配區別:
1、棧(操作系統):由操作系統自動分配釋放 ,存放函數的參數值,局部變數的值等。其操作方式類似於數據結構中的棧;
2、堆(操作系統): 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收,分配方式倒是類似於鏈表。
二、堆棧緩存方式區別:
1、棧使用的是一級緩存, 他們通常都是被調用時處於存儲空間中,調用完畢立即釋放;
2、堆是存放在二級緩存中,生命周期由虛擬機的垃圾回收演算法來決定(並不是一旦成為孤兒對象就能被回收)。所以調用這些對象的速度要相對來得低一些。
三、堆棧數據結構區別:
堆(數據結構):堆可以被看成是一棵樹,如:堆排序;
棧(數據結構):一種先進後出的數據結構。

『玖』 c語言中堆和棧的區別

堆:指的是認為用代碼動態申請的內存空間,所有手動釋放。例如:malloc的內存
棧:就是當變數生命周期結束,由系統自動回收內存。