閱讀898 返回首頁    go 阿裏雲 go 技術社區[雲棲]


c語言基礎(五)之內存、堆棧區

 

 

指針運算:

指針的運算在數組的運算中才有意義。其它指針操作的運算都無意義。

 

隻要是指針類型,它在內存中所占的長度都是4個byte。(前提是32位係統)

 

傳統數組被創建出來,它是被創建在棧空間上的。也就是說程序員沒有辦法

去清空棧空間上的內容。

 

動態內存分配:

使用malloc函數,能夠動態分配內存。注意要引入#include<malloc.h>函數頭文件

malloc(a);a表示int類型參數。就是要申請多少個byte長度的內存。

       返回值 :是申請縣的空間的首地址(void類型)。它是一個指針類型的返回值。

                      要作相應的強製類型轉換。

釋放空間free(p);//p首地址

記住:在free後盡量不要在使用該變量。

       避免錯誤方法:在釋放free(p)後,p=NULL(大寫);若其它地方有使用p,則會有錯誤提示。

 

用動態分配內存,可以在主函數中使用子函數的變量的值。

 

例子:

int len=0;

scanf("%d",&len);

int* p = (int*)malloc(sizeof(int)*len)//若len=6,執行完畢後,申請了多少byte內存?

 //1.靜態申請的內存 int* 4byte

 //2.動態內存4*6=24byte

 //所以,總共申請了 24+4 = 28byte內存

 

realloc(p,q);//p表示:重新分配哪一塊內存空間,q表示:重新分配的大小

           返回值:是內存空間的首地址。

 

靜態內存和動態內存:

靜態內存是程序編譯執行後係統自動分配的,由係統自動釋放。靜態內存

                 是棧分配的。動態內存是堆分配的。

 

靜態內存和動態內存區別:

1.從靜態存儲區域分配。內存在程序編譯的時候就已經分配好,這塊內存在

    程序的整個運行期間都存在。例如:全局變量,static變量

2.在棧上創建。在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,

    函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置於處理器的

    指令集中,效率很高,但是分配的內存容量有限。

3.從堆上分配,亦稱動態內存分配。程序在運行的時候用mallo(c)c或new(java)申請任意

   多少的內存,程序員自己負責在何時用free或delete釋放內存。動態內存的生存

   期由我們決定,使用非常靈活,但問題也最多。

 

堆和棧的區別:

1.申請方式:

棧:由係統自動分配,例如,聲明一個局部變量int b;係統自動在棧中為b開辟空間,

        棧空間是後進先出,由係統釋放空間。

堆:需要程序員自己申請,並指明大小,在c中用malloc函數

        如:p1=(char*)malloc(10);

              但是注意p1本身是在棧中的。

2.申請後係統的響應

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

堆:首先應該知道操作係統有一個記錄空閑內存地址的鏈表,當係統收到程序的申請時,

       會遍曆該鏈表,尋找第一個空間大於所申請空間的堆結點,然後將該結點從空閑結點

       鏈表中刪除,並將該結點的空間分配給程序,另外,對於大多數係統,會在這塊內存

       空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放

       本內存空間。另外,由於找到的堆結點的大小不一定正好等於申請的大小,係統會自動

       的將多餘的那部分重新放入空閑鏈表中。

3.申請大小的限製

棧:在windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的

        意思是棧頂的地址和棧的最大容量是係統預先規定好的,在windows下,棧的大小是

        2M(vc編譯選項中可以設置,其實就是一個stack參數,缺省值2M),如果申請的空間

        超過酷我剩餘空間時,將提示overflow。因此,能從棧獲得的空間比較小。

堆:是向高地址擴展的數據結構,是不連續的內存區域。這是由於係統是用鏈表來存儲的空閑

        內存地址的,自然是不連續的。而鏈表的遍曆方向是由低向高地址。堆的大小受限於計算機

        係統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。

4.申請效率的比較:

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

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

5堆和棧的存儲內容:

棧:在函數調用時,第一個進棧的是主函數中後的下一條指令(函數調用語句的下一條可執行

       語句 )的地址,然後是函數的各個參數,在大多數的c編譯器中,參數是由右往左入棧的,

      然後是函數中的局部變量。注意:靜態變量是不入棧的。

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

6.內存的回收

棧:棧上的分配的內存,編譯器會自動回收。

堆:堆上分配的內存,要通過free來顯示的收回,否則會造成內存泄漏。

 

                               

 

 

最後更新:2017-04-02 17:09:25

  上一篇:go Asp.net中把Excel數據存儲至SQL Server中
  下一篇:go jni使用基礎(九)之c調用java事例demo