C語言內(nèi)存的動態(tài)分配比較malloc和realloc的區(qū)別
C—動態(tài)內(nèi)存分配之malloc與realloc的區(qū)別
在程序的執(zhí)行期間分配內(nèi)存時,內(nèi)存區(qū)域中的這個空間稱為堆(heap)。還有另一個內(nèi)存區(qū)域,稱為棧(stack),其中的空間分配給函數(shù)的參數(shù)和本地變量。在執(zhí)行完該函數(shù)后,存儲參數(shù)和本地變量的內(nèi)存空間就會釋放。堆中的內(nèi)存是由程序員控制的。在分配堆上的內(nèi)存時,由程序員跟蹤所分配的內(nèi)存何時不再需要,并釋放這些空間,以便于以后重用它們。
使用動態(tài)內(nèi)存很明顯的好處就是:不需要預(yù)先分配存儲空間且分配的空間可以根據(jù)程序的需要擴大或縮小,這樣可以有效的使用內(nèi)存空間。
malloc和free
C函數(shù)庫中的malloc和free分別用于執(zhí)行動態(tài)內(nèi)存分配和釋放。這兩個函數(shù)的原型如下所示,他們都在頭文件stdlib.h中聲明。
void *malloc ( size_t size );
void free ( void *pointer );
malloc的作用是在內(nèi)存的動態(tài)存儲區(qū)中分配一個長度為size的連續(xù)空間。其參數(shù)是一個無符號整形數(shù),返回值是一個指向所分配的連續(xù)存儲域的起始地址的指針。還有一點必須注意的是,當(dāng)函數(shù)未能成功分配存儲空間(如內(nèi)存不足)就會返回一個NULL指針。所以在調(diào)用該函數(shù)時應(yīng)該檢測返回值是否為NULL,確保非空之后再使用非常重要。malloc所分配的內(nèi)存是一塊連續(xù)的空間。同時,malloc實際分配的內(nèi)存空間可能會比你請求的多一點,但是這個行為只是由編譯器定義的。malloc不知道用戶所請求的內(nèi)存需要存儲的數(shù)據(jù)類型,所以malloc返回一個void *的指針,它可以轉(zhuǎn)換為其它任何類型的指針。
由于內(nèi)存區(qū)域總是有限的,不能不限制地分配下去,而且一個程序要盡量節(jié)省資源,所以當(dāng)所分配的內(nèi)存區(qū)域不用時,就要釋放它,以便其它的變量或者程序使用。這時我們就要用到free函數(shù)。free的參數(shù)必須要么是NULL,要么是從malloc、relloc、calloc返回的值。作用是釋放之前返回的指針指向的內(nèi)存空間,向free傳遞一個NULL參數(shù)不會產(chǎn)生任何效果。
calloc和realloc與malloc的區(qū)別
calloc和realloc的原型如下:
void *calloc ( size_t num_elements, size_t element_size );
void *realloc (void *ptr, size_t new_size );
calloc和malloc 主要的區(qū)別在于前者在返回內(nèi)存的指針之前將它初始化為0,另外它們請求數(shù)量的方式不同。calloc的參數(shù)包括所需元素的數(shù)量和每個元素的字節(jié),根據(jù)這些值可以計算出總共需要分配的內(nèi)存空間。
realloc函數(shù)用于修改一個原先已經(jīng)分配的內(nèi)存塊的大小,可以使一塊內(nèi)存的擴大或縮小。當(dāng)起始空間的地址為空,即*ptr = NULL,則同malloc。當(dāng)*ptr非空:若nuw_size < size,即縮小*ptr所指向的內(nèi)存空間,該內(nèi)存塊尾部的部分內(nèi)存被拿掉,剩余部分內(nèi)存的原先內(nèi)容依然保留;若nuw_size > size,即擴大*ptr所指向的內(nèi)存空間,如果原先的內(nèi)存尾部有足夠的擴大空間,則直接在原先的內(nèi)存塊尾部新增內(nèi)存,如果原先的內(nèi)存尾部空間不足,或原先的內(nèi)存塊無法改變大小,realloc將重新分配另一塊nuw_size大小的內(nèi)存,并把原先那塊內(nèi)存的內(nèi)容復(fù)制到新的內(nèi)存塊上。因此,使用realloc后就應(yīng)該改用realloc返回的新指針。
使用方法程序示例
int *ptr =NULL; ptr = (int*)malloc(sizeof(int)*size); if (*ptr == NULL) { strerror(error); return; }
上例中動態(tài)分配了size個整型存儲區(qū)域。動態(tài)分配內(nèi)存的步驟可細(xì)分為:分配size個整型的連續(xù)存儲空間,并返回一個指向其起始地址的整型指針把此整型指針地址賦給ptr, 檢測返回值是否為NULL。注意,類型轉(zhuǎn)換(int*)將函數(shù)返回的地址轉(zhuǎn)換成int類型的指針。這么做是因為malloc()是一般用途的函數(shù),可為任何類型的數(shù)據(jù)分配內(nèi)存。sizeof是一個運算符,它返回一個size_t類型的無符號整數(shù),該整數(shù)是存儲它的參數(shù)需要的字節(jié)數(shù)。它把關(guān)鍵字如int或float等作為參數(shù),返回存儲該類型的數(shù)據(jù)項所需的字節(jié)數(shù)。它的參數(shù)也可以是變量或數(shù)組名。把數(shù)組名作為參數(shù)時,sizeof返回存儲整個數(shù)組所需的字節(jié)數(shù)。前一個例子請求分配足以存儲size個int數(shù)據(jù)項的內(nèi)存。以這種方式使用sizeof,可以根據(jù)不同的C編譯器為int類型的值自動調(diào)整所需的內(nèi)存空間。
int *p1,*p2; p1 = (int*)malloc(size * sizeof(int)); p2=p1; …… free(p1); /*或者free(p2)*/
給free函數(shù)傳遞其它的值很可能造成死機或其它災(zāi)難性的后果。注意:這里重要的是指針的值,而不是用來申請動態(tài)內(nèi)存的指針本身。
malloc返回值賦給p1,又把p1的值賦給p2,所以此時p1,p2都可作為free函數(shù)的參數(shù)。malloc函數(shù)是對存儲區(qū)域進行分配的。 free函數(shù)是釋放已經(jīng)不用的內(nèi)存區(qū)域的。 所以由這兩個函數(shù)就可以實現(xiàn)對內(nèi)存區(qū)域進行動態(tài)分配并進行簡單的管理了。
下面是使用動態(tài)分配的內(nèi)存的基本規(guī)則:
- 避免分配大量的小內(nèi)存塊。分配堆上的內(nèi)存有一些系統(tǒng)開銷,所以分配許多小的內(nèi)存塊比分配幾個大內(nèi)存塊的系統(tǒng)開銷大。
- 僅在需要時分配內(nèi)存。只要使用完堆上的內(nèi)存塊,就釋放它。
- 總是確保釋放已分配的內(nèi)存。在編寫分配內(nèi)存的代碼時,就要確定在代碼的什么地方釋放內(nèi)存。
- 在釋放內(nèi)存之前,確保不會無意中覆蓋堆上分配的內(nèi)存的地址,否則程序就會出現(xiàn)內(nèi)存泄漏。在循環(huán)中分配內(nèi)存時,要特別小心。
到此這篇關(guān)于C語言內(nèi)存的動態(tài)分配比較malloc和realloc的區(qū)別的文章就介紹到這了,更多相關(guān)C語言比較malloc和realloc內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實現(xiàn)LeetCode(8.字符串轉(zhuǎn)為整數(shù))
這篇文章主要介紹了C++實現(xiàn)LeetCode(8.字符串轉(zhuǎn)為整數(shù)),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07數(shù)據(jù)結(jié)構(gòu) 數(shù)組順序存儲詳細(xì)介紹
這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu) 數(shù)組順序存儲詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下2017-05-05C語言標(biāo)準(zhǔn)時間與秒單位相互轉(zhuǎn)換
這篇文章主要介紹了C語言標(biāo)準(zhǔn)時間與秒單位相互轉(zhuǎn)換,秒單位與標(biāo)準(zhǔn)時間的轉(zhuǎn)換方式,這份代碼一般用在嵌入式單片機里比較多,比如:設(shè)置RTC時鐘的時間,從RTC里讀取秒單位時間后,需要轉(zhuǎn)換成標(biāo)準(zhǔn)時間顯示。下文分享需要的小伙伴可以參考一下2022-05-05