realloc函數(shù)
realloc()函數(shù)可以重用或擴(kuò)展以前用malloc()、calloc()及realloc()函數(shù)自身分配的內(nèi)存。
函數(shù)原型:
extern void *realloc(void *mem_address, unsigned int newsize); //指針名 = (數(shù)據(jù)類(lèi)型*) realloc (要改變內(nèi)存大小的指針名,新的大小)。 //新的大小一定要大于原來(lái)的大小,不然的話(huà)會(huì)導(dǎo)致數(shù)據(jù)丟失! //如果newsize大小為0,那么釋放mem_address指向的內(nèi)存,并返回NULL。
先判斷當(dāng)前的指針是否有足夠的連續(xù)空間,如果有,擴(kuò)大mem_address指向的地址,并且將 mem_address返回,如果空間不夠,先按照 newsize 指定的大小分配空間,將原有數(shù)據(jù)從頭到尾拷貝到新分配的內(nèi)存區(qū)域,而后釋放原來(lái) mem_address 所指內(nèi)存區(qū)域(注意:原來(lái)指針是自動(dòng)釋放,不需要使用free),同時(shí)返回新分配的內(nèi)存區(qū)域的首地址。即重新分配存儲(chǔ)器塊的地址。
1、 realloc()函數(shù)需兩個(gè)參數(shù):一個(gè)是包含地址的指針(該地址由之前的malloc()、calloc()或realloc()函數(shù)返回),另一個(gè)是要新分配的內(nèi)存字節(jié)數(shù)。
2、 realloc()函數(shù)分配第二個(gè)參數(shù)指定的內(nèi)存量,并把第一個(gè)參數(shù)指針指向的之前分配的內(nèi)容復(fù)制到新配的內(nèi)存中,且復(fù)制的內(nèi)容長(zhǎng)度等于新舊內(nèi)存區(qū)域中較小的那一個(gè)。即新內(nèi)存大于原內(nèi)存,則原內(nèi)存所有內(nèi)容復(fù)制到新內(nèi)存,如果新內(nèi)存小于原內(nèi)存,只復(fù)制長(zhǎng)度等于新內(nèi)存空間的內(nèi)容。
3、realloc()函數(shù)的第一個(gè)參數(shù)若為空指針,相當(dāng)于分配第二個(gè)參數(shù)指定的新內(nèi)存空間,此時(shí)等價(jià)于malloc()、calloc()或realloc()函數(shù)。
4、如果是將分配的內(nèi)存擴(kuò)大,則有以下3種情況:
1) 如果當(dāng)前內(nèi)存段后面有需要的內(nèi)存空間,則直接擴(kuò)展這段內(nèi)存空間,realloc()將返回原指針。
2) 如果當(dāng)前內(nèi)存段后面的空閑字節(jié)不夠,那么就使用堆中的第一個(gè)能夠滿(mǎn)足這一要求的內(nèi)存塊,將目前的數(shù)據(jù)復(fù)制到新的位置,并將原來(lái)的數(shù)據(jù)塊釋放掉,返回新的內(nèi)存塊地址位置。
3) 如果申請(qǐng)失敗,將返回NULL,此時(shí),原來(lái)的指針仍然有效。
注意事項(xiàng):
1、第一個(gè)參數(shù)要么是空指針,要么是指向以前分配的內(nèi)存。如果不指向以前分配的內(nèi)存或指向已釋放的內(nèi)存,結(jié)果就是不確定的。
2、 如果調(diào)用成功,不管當(dāng)前內(nèi)存段后面的空閑空間是否滿(mǎn)足要求,都會(huì)釋放掉原來(lái)的指針,重新返回一個(gè)指針,雖然返回的指針有可能和原來(lái)的指針一樣,即不能再次釋放掉原來(lái)的指針。
返回值:如果重新分配成功則返回指向被分配內(nèi)存的指針,否則返回空指針NULL。
注意:這里原始內(nèi)存中的數(shù)據(jù)還是保持不變的。當(dāng)內(nèi)存不再使用時(shí),應(yīng)使用free()等函數(shù)將內(nèi)存塊釋放
#include#include int main() { int i; int *t; int*pn = (int*)malloc(10 * sizeof(int));//這里只是申請(qǐng)10個(gè)int的空間 t = pn; for (i = 0; i < 10; i++) { //賦值 pn[i] = i; } //如果將這里的數(shù)值改大就將有可能出現(xiàn)空閑空間不足,從而申請(qǐng)一塊新內(nèi)存 pn = (int*)realloc(pn, 20 * sizeof(int)); //多擴(kuò)充10個(gè)int空間加上之前的就是一共20個(gè)int for (i = 10; i < 20; i++) {//再賦值 注意從第10個(gè)開(kāi)始的 pn[i] = i; } for (i = 0; i < 20; i++) {//輸出 printf("%3d", pn[i]); } printf(" "); printf("p=%p t=%p ", pn, t);//輸出地址 free(pn);//釋放空間 pn = NULL;//指針指空 return 0; } 如果申請(qǐng)空間的數(shù)值較小,原來(lái)申請(qǐng)的動(dòng)態(tài)內(nèi)存后面還有空余內(nèi)存,系統(tǒng)將直接在原內(nèi)存空間后面擴(kuò)容 并返回原動(dòng)態(tài)空間基地址;如果申請(qǐng)空間的數(shù)值較大,原來(lái)申請(qǐng)的空間后面沒(méi)有足夠大的空間擴(kuò)容, 系統(tǒng)將重新申請(qǐng)一塊新的內(nèi)存,并把原來(lái)空間的內(nèi)容拷貝過(guò)去,原來(lái)空間OS自動(dòng)free;如果申請(qǐng)空間的數(shù)值非常大, 系統(tǒng)內(nèi)存申請(qǐng)失敗,返回NULL,原來(lái)的內(nèi)存不會(huì)釋放。注意:如果擴(kuò)容后的內(nèi)存空間較原空間小,將會(huì)出現(xiàn)數(shù)據(jù)丟失, 如果直接realloc(p, 0);相當(dāng)于free(p).
使用總結(jié):
(1)realloc失敗的時(shí)候,返回NULL
(2)realloc失敗的時(shí)候,原來(lái)的內(nèi)存不改變,不會(huì)釋放也不會(huì)移動(dòng)
(3)假如原來(lái)的內(nèi)存后面還有足夠多剩余內(nèi)存的話(huà),realloc的內(nèi)存=原來(lái)的內(nèi)存+剩余內(nèi)存,realloc還是返回原來(lái)內(nèi)存的地址; 假如原來(lái)的內(nèi)存后面沒(méi)有足夠多剩余內(nèi)存的話(huà),realloc將申請(qǐng)新的內(nèi)存,然后把原來(lái)的內(nèi)存數(shù)據(jù)拷貝到新內(nèi)存里,原來(lái)的內(nèi)存將被free掉,realloc返回新內(nèi)存的地址
(4)如果size為0,效果等同于free()。這里需要注意的是只對(duì)指針本身進(jìn)行釋放,例如對(duì)二維指針**a,對(duì)a調(diào)用realloc時(shí)只會(huì)釋放一維,使用時(shí)謹(jǐn)防內(nèi)存泄露。
(5)傳遞給realloc的指針必須是先前通過(guò)malloc(),calloc(), 或realloc()分配的
(6)傳遞給realloc的指針可以為空,等同于malloc。
malloc與free函數(shù)
malloc中文叫動(dòng)態(tài)內(nèi)存分配,用于申請(qǐng)一塊連續(xù)的指定大小的內(nèi)存塊區(qū)域以void*類(lèi)型返回分配的內(nèi)存區(qū)域地址,當(dāng)無(wú)法知道內(nèi)存具體位置的時(shí)候,想要綁定真正的內(nèi)存空間,就需要用到動(dòng)態(tài)的分配內(nèi)存,且分配的大小就是程序要求的大小。
函數(shù)原型:
void * malloc(size_t size); 在以前 malloc返回的是char型指針,新的ANSIC標(biāo)準(zhǔn)規(guī)定,該函數(shù)返回為void型指針,因此必要時(shí)要進(jìn)行類(lèi)型轉(zhuǎn)換。 它能向系統(tǒng)申請(qǐng)分配一個(gè)長(zhǎng)度為num_bytes(或size)個(gè)字節(jié)的內(nèi)存塊。 其作用是在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)中分配一個(gè)長(zhǎng)度為size的連續(xù)空間。當(dāng)函數(shù)申請(qǐng)內(nèi)存分配成功時(shí), 此函數(shù)的返回值是分配區(qū)域的起始地址,或者說(shuō),此函數(shù)是一個(gè)指針型函數(shù),返回的指針指向該分配域的開(kāi)頭位置。 (它返回的是分配得到的內(nèi)存的首字節(jié)地址),如果無(wú)法獲得符合要求的內(nèi)存塊,malloc函數(shù)會(huì)返回空指針
size為要申請(qǐng)的空間大小,需要我們手動(dòng)的去計(jì)算,如int *p = (int * )malloc(20*sizeof(int)),如果編譯器默認(rèn)int為4字節(jié)存儲(chǔ)的話(huà),那么計(jì)算結(jié)果是80 Byte,一次申請(qǐng)一個(gè)80 Byte的連續(xù)空間,并將空間基地址強(qiáng)制轉(zhuǎn)換為int類(lèi)型,賦值給指針p,此時(shí)申請(qǐng)的內(nèi)存值是不確定的。
malloc函數(shù)的實(shí)質(zhì)體現(xiàn)在,它有一個(gè)將可用的內(nèi)存塊連接為一個(gè)長(zhǎng)長(zhǎng)的列表的所謂 空閑鏈表的功能。
調(diào)用malloc函數(shù)時(shí),它沿連接表尋找一個(gè)大到足以滿(mǎn)足用戶(hù)請(qǐng)求所需要的內(nèi)存塊。然后,將該內(nèi)存塊一分為二(一塊的大小與用戶(hù)請(qǐng)求的大小相等,另一塊的大小就是剩下的字節(jié))。接下來(lái),將分配給用戶(hù)的那塊內(nèi)存?zhèn)鹘o用戶(hù),并將剩下的那塊(如果有的話(huà))返回到連接表上。
調(diào)用free函數(shù)時(shí),它將用戶(hù)釋放的內(nèi)存塊連接到空閑鏈上。到最后,空閑鏈會(huì)被切成很多的小內(nèi)存片段,如果這時(shí)用戶(hù)申請(qǐng)一個(gè)大的內(nèi)存片段,那么空閑鏈上可能沒(méi)有可以滿(mǎn)足用戶(hù)要求的片段了。
于是,malloc函數(shù)請(qǐng)求延時(shí),并開(kāi)始在空閑鏈上翻箱倒柜地檢查各內(nèi)存片段,對(duì)它們進(jìn)行整理,將相鄰的小空閑塊合并成較大的內(nèi)存塊。如果無(wú)法獲得符合要求的內(nèi)存塊,malloc函數(shù)會(huì)返回NULL指針(空指針),因此在調(diào)用malloc動(dòng)態(tài)申請(qǐng)內(nèi)存塊時(shí),一定要進(jìn)行返回值的判斷。
#include#include int main(void) { int count, *array; /*count是一個(gè)計(jì)數(shù)器,array是一個(gè)整型指針,也可以理解為指向一個(gè)整型數(shù)組的首地址*/ if ((array=(int *) malloc(10 * sizeof(int))) == NULL)//把類(lèi)型強(qiáng)制轉(zhuǎn)換為int 申請(qǐng)內(nèi)存空間 10個(gè)int的空間 //一個(gè)int大小是sizeof(int) { printf("不能成功分配存儲(chǔ)空間。"); exit(1); //強(qiáng)制結(jié)束程序 } for (count = 0; count < 10; count++) { /*給數(shù)組賦值*/ array[count] = count; } for (count = 0; count < 10; count++) { /*打印數(shù)組元素*/ printf("%2d", array[count]); } return 0; }
free函數(shù):
free()是C語(yǔ)言中釋放內(nèi)存空間的函數(shù),通常與申請(qǐng)內(nèi)存空間的函數(shù)malloc()結(jié)合使用,可以釋放由 malloc()、calloc()、realloc() 等函數(shù)申請(qǐng)的內(nèi)存空間。
函數(shù)原型:
void free(void *ptr); ptr-- 指針指向一個(gè)要釋放內(nèi)存的內(nèi)存塊,該內(nèi)存塊之前是通過(guò)調(diào)用 malloc、calloc 或 realloc 進(jìn)行分配內(nèi)存的。如果傳遞的參數(shù)是一個(gè)空指針,則不會(huì)執(zhí)行任何動(dòng)作。 該函數(shù)不返回任何值。
上面的例子:
#include#include int main(void) { int count, *array; /*count是一個(gè)計(jì)數(shù)器,array是一個(gè)整型指針,也可以理解為指向一個(gè)整型數(shù)組的首地址*/ if ((array=(int *) malloc(10 * sizeof(int))) == NULL)//把類(lèi)型強(qiáng)制轉(zhuǎn)換為int 申請(qǐng)內(nèi)存空間 10個(gè)int的空間 //一個(gè)int大小是sizeof(int) { printf("不能成功分配存儲(chǔ)空間。"); exit(1); //強(qiáng)制結(jié)束程序 } for (count = 0; count < 10; count++) { /*給數(shù)組賦值*/ array[count] = count; } for (count = 0; count < 10; count++) { /*打印數(shù)組元素*/ printf("%2d", array[count]); } free(array); //剛剛沒(méi)有進(jìn)行釋放內(nèi)存 return 0; } ******free的重要性:******* 靜態(tài)內(nèi)存的數(shù)量在編譯時(shí)是固定的,在運(yùn)行期間也不會(huì)改變, 自動(dòng)變量使用的內(nèi)存數(shù)量在程序執(zhí)行期間自動(dòng)增加或減少,但是動(dòng)態(tài)內(nèi)存分配內(nèi)存的數(shù)量只會(huì)增加,除非使用free函數(shù)進(jìn)行釋放 它創(chuàng)建了指針array,并調(diào)用了malloc函數(shù)進(jìn)行內(nèi)存分配了(10* 4(int) )40個(gè)字節(jié)的內(nèi)存,假設(shè),如代碼注釋所示, 遺漏了free,當(dāng)函數(shù)結(jié)束時(shí),作為自動(dòng)變量的指針array也會(huì)消失,但是它所指向的40個(gè)字節(jié)的內(nèi)存卻仍然存在, 由于array指針已被銷(xiāo)毀,所以無(wú)法訪(fǎng)問(wèn)這塊內(nèi)存,它也不能被重復(fù)使用,因?yàn)榇a中沒(méi)有調(diào)用free函數(shù)釋放這塊內(nèi)存, 如果是一個(gè)函數(shù),當(dāng)?shù)诙握{(diào)用它時(shí),它又創(chuàng)建了array指針,并調(diào)用malloc分配40個(gè)字節(jié)的內(nèi)存,第一次調(diào)用的40個(gè)字節(jié)的內(nèi)存已不可用, 所以malloc函數(shù)分配了另外的內(nèi)存,當(dāng)函數(shù)結(jié)束時(shí)該內(nèi)存也無(wú)法被訪(fǎng)問(wèn)和再使用,如果循環(huán)要進(jìn)行1000次,那么每一次的調(diào)用都會(huì)分配內(nèi)存, 持續(xù)增加,實(shí)際上,等不到程序結(jié)束,內(nèi)存早已被耗盡,這類(lèi)問(wèn)題被稱(chēng)為內(nèi)存泄漏,所以 為防止這類(lèi)問(wèn)題的發(fā)生, 必須要在動(dòng)態(tài)內(nèi)存分配函數(shù)后加上free函數(shù)釋放內(nèi)存。
總結(jié):
malloc 必須要由我們計(jì)算字節(jié)數(shù),并且在返回后強(qiáng)行轉(zhuǎn)換為實(shí)際類(lèi)型的指針。另外有一點(diǎn)不能直接看出的區(qū)別是,malloc 只管分配內(nèi)存,并不能對(duì)所得的內(nèi)存進(jìn)行初始化,所以得到的一片新內(nèi)存中,其值將是隨機(jī)的
一般使用后要使用free(起始地址的指針) 對(duì)內(nèi)存進(jìn)行釋放,不然內(nèi)存申請(qǐng)過(guò)多會(huì)導(dǎo)致內(nèi)存泄漏會(huì)影響計(jì)算機(jī)的性能,以至于得重啟電腦。如果使用過(guò)后不清零,還可以使用該指針對(duì)該塊內(nèi)存進(jìn)行訪(fǎng)問(wèn)。
通常,malloc函數(shù)要和free函數(shù)一起配對(duì)使用,free函數(shù)的參數(shù)是之前mallloc函數(shù)返回的地址(指針),該函數(shù)釋放之前malloc函數(shù)分配的內(nèi)存,因此,動(dòng)態(tài)內(nèi)存分配的存儲(chǔ)期是從動(dòng)態(tài)內(nèi)存分配函數(shù)malloc(或其他)到f調(diào)用ree函數(shù)釋放內(nèi)存為止,涉嫌malloc和free函數(shù)管理著一個(gè)內(nèi)存池。
每次調(diào)用malloc分配內(nèi)存給程序使用,每次調(diào)用free函數(shù)把內(nèi)存空間歸還給內(nèi)存池中,這樣便可以重復(fù)使用這些內(nèi)存,free函數(shù)的參數(shù)應(yīng)該是一個(gè)指針,指向由malloc函數(shù)分配的一塊內(nèi)存,不能用free函數(shù)釋放通過(guò)其他方式(如 :聲明一個(gè)數(shù)組),分配的內(nèi)存,malloc函數(shù)和free函數(shù)的原型都在stdio.h頭文件中。
審核編輯:郭婷
-
存儲(chǔ)器
+關(guān)注
關(guān)注
39文章
7738瀏覽量
171652 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4417瀏覽量
67501
原文標(biāo)題:【零基礎(chǔ)學(xué)C語(yǔ)言】?jī)?nèi)存知識(shí)總結(jié):realloc函數(shù)和free函數(shù)
文章出處:【微信號(hào):cyuyanxuexi,微信公眾號(hào):C語(yǔ)言編程學(xué)習(xí)基地】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
BNC轉(zhuǎn)接頭接線(xiàn)注意事項(xiàng)
迅為RK3588開(kāi)發(fā)板Android系統(tǒng)燒寫(xiě)及注意事項(xiàng)
驅(qū)動(dòng)板PCB布線(xiàn)的注意事項(xiàng)
emWin AppWizard 開(kāi)發(fā)注意事項(xiàng)有哪些?
別讓這些細(xì)節(jié)毀了PCBA!焊接注意事項(xiàng)清單
美國(guó)Odyssey奧德賽電池充電注意事項(xiàng)全解析
IGBT器件的防靜電注意事項(xiàng)
手機(jī)喇叭氣密性檢測(cè)儀的注意事項(xiàng)
設(shè)置射頻網(wǎng)絡(luò)分析儀的測(cè)試條件有哪些注意事項(xiàng)
錐齒輪減速機(jī)的使用安裝和維護(hù)維修注意事項(xiàng)
realloc函數(shù)和free函數(shù)的實(shí)驗(yàn)及注意事項(xiàng)
評(píng)論