C語(yǔ)言內(nèi)存的動(dòng)態(tài)分配比較malloc和realloc的區(qū)別
C—?jiǎng)討B(tài)內(nèi)存分配之malloc與realloc的區(qū)別
在程序的執(zhí)行期間分配內(nèi)存時(shí),內(nèi)存區(qū)域中的這個(gè)空間稱為堆(heap)。還有另一個(gè)內(nèi)存區(qū)域,稱為棧(stack),其中的空間分配給函數(shù)的參數(shù)和本地變量。在執(zhí)行完該函數(shù)后,存儲(chǔ)參數(shù)和本地變量的內(nèi)存空間就會(huì)釋放。堆中的內(nèi)存是由程序員控制的。在分配堆上的內(nèi)存時(shí),由程序員跟蹤所分配的內(nèi)存何時(shí)不再需要,并釋放這些空間,以便于以后重用它們。
使用動(dòng)態(tài)內(nèi)存很明顯的好處就是:不需要預(yù)先分配存儲(chǔ)空間且分配的空間可以根據(jù)程序的需要擴(kuò)大或縮小,這樣可以有效的使用內(nèi)存空間。
malloc和free
C函數(shù)庫(kù)中的malloc和free分別用于執(zhí)行動(dòng)態(tài)內(nèi)存分配和釋放。這兩個(gè)函數(shù)的原型如下所示,他們都在頭文件stdlib.h中聲明。
void *malloc ( size_t size );
void free ( void *pointer );
malloc的作用是在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)中分配一個(gè)長(zhǎng)度為size的連續(xù)空間。其參數(shù)是一個(gè)無(wú)符號(hào)整形數(shù),返回值是一個(gè)指向所分配的連續(xù)存儲(chǔ)域的起始地址的指針。還有一點(diǎn)必須注意的是,當(dāng)函數(shù)未能成功分配存儲(chǔ)空間(如內(nèi)存不足)就會(huì)返回一個(gè)NULL指針。所以在調(diào)用該函數(shù)時(shí)應(yīng)該檢測(cè)返回值是否為NULL,確保非空之后再使用非常重要。malloc所分配的內(nèi)存是一塊連續(xù)的空間。同時(shí),malloc實(shí)際分配的內(nèi)存空間可能會(huì)比你請(qǐng)求的多一點(diǎn),但是這個(gè)行為只是由編譯器定義的。malloc不知道用戶所請(qǐng)求的內(nèi)存需要存儲(chǔ)的數(shù)據(jù)類型,所以malloc返回一個(gè)void *的指針,它可以轉(zhuǎn)換為其它任何類型的指針。
由于內(nèi)存區(qū)域總是有限的,不能不限制地分配下去,而且一個(gè)程序要盡量節(jié)省資源,所以當(dāng)所分配的內(nèi)存區(qū)域不用時(shí),就要釋放它,以便其它的變量或者程序使用。這時(shí)我們就要用到free函數(shù)。free的參數(shù)必須要么是NULL,要么是從malloc、relloc、calloc返回的值。作用是釋放之前返回的指針指向的內(nèi)存空間,向free傳遞一個(gè)NULL參數(shù)不會(huì)產(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,另外它們請(qǐng)求數(shù)量的方式不同。calloc的參數(shù)包括所需元素的數(shù)量和每個(gè)元素的字節(jié),根據(jù)這些值可以計(jì)算出總共需要分配的內(nèi)存空間。
realloc函數(shù)用于修改一個(gè)原先已經(jīng)分配的內(nèi)存塊的大小,可以使一塊內(nèi)存的擴(kuò)大或縮小。當(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,即擴(kuò)大*ptr所指向的內(nèi)存空間,如果原先的內(nèi)存尾部有足夠的擴(kuò)大空間,則直接在原先的內(nèi)存塊尾部新增內(nèi)存,如果原先的內(nèi)存尾部空間不足,或原先的內(nèi)存塊無(wú)法改變大小,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; }
上例中動(dòng)態(tài)分配了size個(gè)整型存儲(chǔ)區(qū)域。動(dòng)態(tài)分配內(nèi)存的步驟可細(xì)分為:分配size個(gè)整型的連續(xù)存儲(chǔ)空間,并返回一個(gè)指向其起始地址的整型指針把此整型指針地址賦給ptr, 檢測(cè)返回值是否為NULL。注意,類型轉(zhuǎn)換(int*)將函數(shù)返回的地址轉(zhuǎn)換成int類型的指針。這么做是因?yàn)閙alloc()是一般用途的函數(shù),可為任何類型的數(shù)據(jù)分配內(nèi)存。sizeof是一個(gè)運(yùn)算符,它返回一個(gè)size_t類型的無(wú)符號(hào)整數(shù),該整數(shù)是存儲(chǔ)它的參數(shù)需要的字節(jié)數(shù)。它把關(guān)鍵字如int或float等作為參數(shù),返回存儲(chǔ)該類型的數(shù)據(jù)項(xiàng)所需的字節(jié)數(shù)。它的參數(shù)也可以是變量或數(shù)組名。把數(shù)組名作為參數(shù)時(shí),sizeof返回存儲(chǔ)整個(gè)數(shù)組所需的字節(jié)數(shù)。前一個(gè)例子請(qǐng)求分配足以存儲(chǔ)size個(gè)int數(shù)據(jù)項(xiàng)的內(nèi)存。以這種方式使用sizeof,可以根據(jù)不同的C編譯器為int類型的值自動(dòng)調(diào)整所需的內(nèi)存空間。
int *p1,*p2; p1 = (int*)malloc(size * sizeof(int)); p2=p1; …… free(p1); /*或者free(p2)*/
給free函數(shù)傳遞其它的值很可能造成死機(jī)或其它災(zāi)難性的后果。注意:這里重要的是指針的值,而不是用來(lái)申請(qǐng)動(dòng)態(tài)內(nèi)存的指針本身。
malloc返回值賦給p1,又把p1的值賦給p2,所以此時(shí)p1,p2都可作為free函數(shù)的參數(shù)。malloc函數(shù)是對(duì)存儲(chǔ)區(qū)域進(jìn)行分配的。 free函數(shù)是釋放已經(jīng)不用的內(nèi)存區(qū)域的。 所以由這兩個(gè)函數(shù)就可以實(shí)現(xiàn)對(duì)內(nèi)存區(qū)域進(jìn)行動(dòng)態(tài)分配并進(jìn)行簡(jiǎn)單的管理了。
下面是使用動(dòng)態(tài)分配的內(nèi)存的基本規(guī)則:
- 避免分配大量的小內(nèi)存塊。分配堆上的內(nèi)存有一些系統(tǒng)開(kāi)銷,所以分配許多小的內(nèi)存塊比分配幾個(gè)大內(nèi)存塊的系統(tǒng)開(kāi)銷大。
- 僅在需要時(shí)分配內(nèi)存。只要使用完堆上的內(nèi)存塊,就釋放它。
- 總是確保釋放已分配的內(nèi)存。在編寫(xiě)分配內(nèi)存的代碼時(shí),就要確定在代碼的什么地方釋放內(nèi)存。
- 在釋放內(nèi)存之前,確保不會(huì)無(wú)意中覆蓋堆上分配的內(nèi)存的地址,否則程序就會(huì)出現(xiàn)內(nèi)存泄漏。在循環(huán)中分配內(nèi)存時(shí),要特別小心。
到此這篇關(guān)于C語(yǔ)言內(nèi)存的動(dòng)態(tài)分配比較malloc和realloc的區(qū)別的文章就介紹到這了,更多相關(guān)C語(yǔ)言比較malloc和realloc內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言猜兇手及類似題目的實(shí)現(xiàn)示例
本文主要介紹了C語(yǔ)言猜兇手及類似題目的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01C++實(shí)現(xiàn)LeetCode(8.字符串轉(zhuǎn)為整數(shù))
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(8.字符串轉(zhuǎn)為整數(shù)),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07數(shù)據(jù)結(jié)構(gòu) 數(shù)組順序存儲(chǔ)詳細(xì)介紹
這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu) 數(shù)組順序存儲(chǔ)詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下2017-05-05C語(yǔ)言標(biāo)準(zhǔn)時(shí)間與秒單位相互轉(zhuǎn)換
這篇文章主要介紹了C語(yǔ)言標(biāo)準(zhǔn)時(shí)間與秒單位相互轉(zhuǎn)換,秒單位與標(biāo)準(zhǔn)時(shí)間的轉(zhuǎn)換方式,這份代碼一般用在嵌入式單片機(jī)里比較多,比如:設(shè)置RTC時(shí)鐘的時(shí)間,從RTC里讀取秒單位時(shí)間后,需要轉(zhuǎn)換成標(biāo)準(zhǔn)時(shí)間顯示。下文分享需要的小伙伴可以參考一下2022-05-05C++共享智能指針shared_ptr的實(shí)現(xiàn)
在C++中沒(méi)有垃圾回收機(jī)制,必須自己釋放分配的內(nèi)存,否則就會(huì)造成內(nèi)存泄露,解決這個(gè)問(wèn)題最有效的方法是使用智能指針,本文主要介紹了C++共享智能指針shared_ptr的實(shí)現(xiàn),感興趣的可以了解一下2023-12-12C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易井字棋游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易井字棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04C++?OpenCV紅綠燈檢測(cè)Demo實(shí)現(xiàn)詳解
OpenCV(Open Source Computer Vision Library)是開(kāi)源的計(jì)算機(jī)視覺(jué)和機(jī)器學(xué)習(xí)庫(kù),提供了C++、 C、 Python、 Java接口,并支持Windows、 Linux、 Android、 Mac OS平臺(tái),下面這篇文章主要給大家介紹了關(guān)于C++?OpenCV紅綠燈檢測(cè)Demo實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2022-11-11