c語言棧內存
A. c語言中堆和棧的區別
(1)申請方式
stack:
由系統自動分配。例如,聲明在函數中一個局部變數 int a; 系統自動在棧中為a開辟空間
heap:
需要程序員自己申請,並指明大小,在c中malloc函數
如m1 = (char *)malloc(10);
在C++中用new運算符
如m2 = (char *)malloc(10);
注意:m1、m2本身是在棧中的。
(2)申請後系統的響應
棧:只要棧的剩餘空間大於所申請空間,系統將為程序提供內存,否則將報異常提示棧溢出。
堆: 首先應該知道操作系統有一個記錄空閑內存地址的鏈表,當系統收到程序的申請時,會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,然後將該結點從空閑 結點鏈表中刪除,並將該結點的空間分配給程序,另外,對於大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放本內存空間。另外,由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多餘的那部分重新放入空閑鏈表中。
(3)申請大小的限制及生長方向
棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,在WINDOWS下,棧的大小是2M(也可能是1M,它是一個編譯時就確定的常數),如果申請的空間超過棧的剩餘空間時,將提示overflow。因此,能從棧獲得的空間較小 。
堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲的空閑內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。
(4)申請效率的比較:
棧由系統自動分配,速度較快。但程序員是無法控制的。
堆是由new分配的內存,一般速度比較慢,而且容易產生內存碎片,不過用起來最方便.
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配內存,他不是在堆,也不是在棧是直接在進程的地址空間中保留一快內存,雖然用起來最不方便。但是速度快,也最靈活。
(5)堆和棧中的存儲內容
棧:在函數調用時,第一個進棧的是主函數中後的下一條指令(函數調用語句的下一條可執行語句)的地址,然後是函數的各個參數,在大多數的C編譯器中,參數是由右往左入棧的,然後是函數中的局部變數。注意靜態變數是不入棧的。
當本次函數調用結束後,局部變數先出棧,然後是參數,最後棧頂指針指向最開始存的地址,也就是主函數中的下一條指令,程序由該點繼續運行。
堆:一般是在堆的頭部用一個位元組存放堆的大小。堆中的具體內容有程序員安排。
B. C語言棧區、堆區的使用,typedef和sizeof的使用
1、棧區的使用
棧區寫入內存的的順序是先進後出。
存放的是函數的參數、返回值、局部變數
由編譯器管理數據開辟和釋放
變數的生命周期在該函數結束後自動釋放
不要返回局部變數的值,因為局部變數在函數執行之後就釋放掉了,無法讀取原來的內存
2、堆區的使用
堆區的空間遠遠大於棧區
它沒有先進後出的數據結構
由程序員手動開辟和釋放,malloc、calloc開辟free釋放
注意:
如果主調函數中沒有給指針分配內存,那麼被調函數中需要利用高級指針給主調函數中的指針分配內存
3.數據區放的是靜態變數、全局變數以及常量
static靜態變數: 編譯階段分配內存,只能在當前文件內使用,只初始化一次
ertern全局變數:C語言下默認的全局變數前都默認隱藏了該關鍵字
4.const修飾的變數
直接修改const修飾的全局變數:失敗
簡介修改const修飾的全局變數:失敗,原因是放在常量區,受到保護
直接修改const修飾的局部變數:失敗
直接修改const修飾的局部變數:成功,該局部變數其實放到了棧區,是偽常量
5.字元串常量
不同編譯器的處理方式有所區別
ANSI並未指定它的修改方式
有些編譯器可以修改字元串常量,但有些不可以,某些編譯器將相同的字元串常量看做同一個字元串常量
6.void的使用方式
無類型,不可以創建變數,無法分配內存
限定函數返回值
限定函數參數列表
void*是萬能指針,不需要強制轉化就可以給其他指針賦值
7.sizeof的使用
sizeof的本質其實是一個運算符,類似於+-*/
當統計某類型占的空間時需要加()
當統計mou變數占的空間時無需加()
返回值的類型是無符號整形,即unsigned int
數組名稱如果作為函數參數,會退化為指針,指向數組首元素
8.typedef的使用
它可以給類型起別名
簡化struct關鍵字
區分數據類型
提高代碼的可移植性
C. C語言中的棧和堆是什麼
1、計算機中的內存分為兩部分:一部分是棧(stack,也稱堆棧),另一部分是堆(heap)。
2、 棧,可以看作是一摞卡片,最上面的卡片表示程序的當前作用域,這往往就是當前正在執行的函數。
3、堆,一段完全獨立於當前函數或者棧幀的內存區。如果一個函數中聲明了一些變數,而且希望當這個函數完成時其中聲明的變數仍然存在,就可以將這些變數置於堆中。
D. 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 為最小堆(或者最大堆)。
由此可見,堆是一種特殊的完全二叉樹。其中,節點是從左到右填滿的,並且最後一層的樹葉都在最左邊(即如果一個節點沒有左兒子,那麼它一定沒有右兒子);每個節點的值都小於(或者都大於)其子節點的值。
E. C語言局部變數過多會不會造成棧區堆滿
答案是會的:
系統分配給每個程序的棧空間是有限的,超過了就會堆滿。
最有代表性的就是遞歸函數,如果遞歸的深度達到一定量,程序棧就會滿,程序就會異常退出,之前使用快速排序用到遞歸,當數據量比較大,數據基本有序時遞歸深度就比較大,程序就停止了,調試錯誤顯示棧資源不足。
F. C語言:棧中內存分配是連續的,堆中內存分配是不連續的,對嗎
1、棧中的內存是操作系統自動分配的,可以理解成為時連續的,對中的內存分配是因為我們malloc空間的時候,申請的空間的大小不一樣造成了碎片。使用malloc的時候系統內部有一個空閑內存映射表,系統會自動查找空閑內存中的第一個合適大小的空間分配。
2、每一次分配的內存是連續的,但如果用結構體鏈表來管理分配的內存就可以將每一次分配的內存虛擬的連接起來,但前提是每一次分配的內存還是連續的,只是每個節點所佔的內存單元不是連續的。
G. C語言中函數返回指向棧內存的指針的問題
p是指向局部變數的指針,當函數退出時,局部變數會被釋放,這時,p所指向的位置就不一樣是原來的數。
因為fun()函數返回的值被計算機的臨時變數存放,當賦值給p的時候,p是指向臨時變數的地址,所以還可以讀取出100。
*p = "hello"這是常量字元串,從靜態存儲區分配,第一步字元串"hello"從靜態存儲區獲取一塊內存,指針變數p才指向這塊靜態內存,這塊內存的特點是從程序開始到結束一直從在,所以可以返回。
(7)c語言棧內存擴展閱讀:
函數的返回值類型是在定義函數時指定的。return 語句中表達式的類型應與定義函數時指定的返回值類型一致。如果不一致,則以函數定義時的返回值類型為准,對 return 語句中表達式的類型自動進行轉換,然後再將它返回給主調函數使用。
在調用函數時,如果需要從被調函數返回一個值供主調函數使用,那麼返回值類型必須定義成非 void 型。此時被調函數中必須包含 return 語句,而且 return 後面必須要有返回值,否則就是語法錯誤。
H. C語言中,什麼是棧,什麼是堆
1、棧區(stack):由編譯器自動分配釋放,存放函數的參數值,局部變數等值。局部變數,任務線程函數之類的是放在(使用)棧裡面的,棧利用率高一些。其操作方式類似於數據結構中的棧。特別,棧是屬於線程的,每一個線程會有一個自己的棧。
2、堆區(heap):一般由程序員分配釋放,若程序員不釋放,則可能會引起內存泄漏。注意它和數據結構中的堆是兩回事,分配方式倒是類似於鏈表,常見的就是malloc出來的都是屬於堆區,就像固定出來的區域,到free的時候才釋放,有點類似全局的,靜態的。
(8)c語言棧內存擴展閱讀
棧內存是由編譯器自動分配與釋放的,它有兩種分配方式:靜態分配和動態分配。
1、靜態分配是由編譯器自動完成的,如局部變數的分配(即在一個函數中聲明一個int類型的變數i時,編譯器就會自動開辟一塊內存以存放變數i)。
2、動態分配由alloca函數進行分配,但是棧的動態分配與堆是不同的,它的動態分配是由編譯器進行釋放,無需任何手工實現。
I. C語言中的棧、堆是什麼
C語言中的堆和棧都是一種數據項按序排列的數據結構。
棧就像裝數據的桶或箱子
我們先從大家比較熟悉的棧說起吧,它是一種具有後進先出性質的數據結構,也就是說後存放的先取,先存放的後取。
這就如同我們要取出放在箱子裡面底下的東西(放入的比較早的物體),我們首先要移開壓在它上面的物體(放入的比較晚的物體)。
堆像一棵倒過來的樹
而堆就不同了,堆是一種經過排序的樹形數據結構,每個結點都有一個值。
通常我們所說的堆的數據結構,是指二叉堆。堆的特點是根結點的值最小(或最大),且根結點的兩個子樹也是一個堆。
由於堆的這個特性,常用來實現優先隊列,堆的存取是隨意,這就如同我們在圖書館的書架上取書。
雖然書的擺放是有順序的,但是我們想取任意一本時不必像棧一樣,先取出前面所有的書,書架這種機制不同於箱子,我們可以直接取出我們想要的書。
(9)c語言棧內存擴展閱讀:
關於堆和棧區別的比喻
使用棧就象我們去飯館里吃飯,只管點菜(發出申請)、付錢、和吃(使用),吃飽了就走,不必理會切菜、洗菜等准備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。
使用堆就象是自己動手做喜歡吃的菜餚,比較麻煩,但是比較符合自己的口味,而且自由度大。
參考資料來源:網路-堆棧
J. C語言關於棧的內存釋放問題
是InitStack(s)吧?程序里就沒有InitSqlist()。
因為棧內容沒有初始化,所以訪問那個s->top時就出錯了,並不是分配內存的malloc的問題。
把主函數里這兩行改一下:
Stack *s; /* 這里沒有給s分配內存,這只是一個Stack的指針*/
InitStack(s);
改為:
Stack s; /* 這樣就給s分配空間了, s.top現在就可以用了*/
InitStack(&s);
這個問題就好了。
相應地,以後使用棧時注意使用指針就好:
ShowStack(s);
改為
ShowStack(&s);
還有一種做法,就是在:
Stack *s;
InitStack(s);
中間給指針s分配內存,讓指針s指向正確的結構:
Stack *s;
s = (Stack*)malloc(sizeof(Stack));
InitStack(s);