realloc函數
realloc()函數可以重用或擴展以前用malloc()、calloc()及realloc()函數自身分配的内存。
函數原型:
extern void *realloc(void *mem_address, unsigned int newsize);
//指針名 = (數據類型*) realloc (要改變内存大小的指針名,新的大小)。
//新的大小一定要大于原來的大小,不然的話會導緻數據丢失!
//如果newsize大小為0,那麼釋放mem_address指向的内存,并返回NULL。
先判斷當前的指針是否有足夠的連續空間,如果有,擴大mem_address指向的地址,并且将 mem_address返回,如果空間不夠,先按照 newsize 指定的大小分配空間,将原有數據從頭到尾拷貝到新分配的内存區域,而後釋放原來 mem_address 所指内存區域(注意:原來指針是自動釋放,不需要使用free),同時返回新分配的内存區域的首地址。即重新分配存儲器塊的地址。
1、 realloc()函數需兩個參數:一個是包含地址的指針(該地址由之前的malloc()、calloc()或realloc()函數返回),另一個是要新分配的内存字節數。
2、 realloc()函數分配第二個參數指定的内存量,并把第一個參數指針指向的之前分配的内容複制到新配的内存中,且複制的内容長度等于新舊内存區域中較小的那一個。即新内存大于原内存,則原内存所有内容複制到新内存,如果新内存小于原内存,隻複制長度等于新内存空間的内容。
3、realloc()函數的第一個參數若為空指針,相當于分配第二個參數指定的新内存空間,此時等價于malloc()、calloc()或realloc()函數。
4、如果是将分配的内存擴大,則有以下3種情況:
1) 如果當前内存段後面有需要的内存空間,則直接擴展這段内存空間,realloc()将返回原指針。
2) 如果當前内存段後面的空閑字節不夠,那麼就使用堆中的第一個能夠滿足這一要求的内存塊,将目前的數據複制到新的位置,并将原來的數據塊釋放掉,返回新的内存塊地址位置。
3) 如果申請失敗,将返回NULL,此時,原來的指針仍然有效。
注意事項:
1、第一個參數要麼是空指針,要麼是指向以前分配的内存。如果不指向以前分配的内存或指向已釋放的内存,結果就是不确定的。
2、 如果調用成功,不管當前内存段後面的空閑空間是否滿足要求,都會釋放掉原來的指針,重新返回一個指針,雖然返回的指針有可能和原來的指針一樣,即不能再次釋放掉原來的指針。
返回值:如果重新分配成功則返回指向被分配内存的指針,否則返回空指針NULL。
注意:這裡原始内存中的數據還是保持不變的。當内存不再使用時,應使用free()等函數将内存塊釋放
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i;
int *t;
int*pn = (int*)malloc(10 * sizeof(int));//這裡隻是申請10個int的空間
t = pn;
for (i = 0; i < 10; i ) { //賦值
pn[i] = i;
}
//如果将這裡的數值改大就将有可能出現空閑空間不足,從而申請一塊新内存
pn = (int*)realloc(pn, 20 * sizeof(int)); //多擴充10個int空間加上之前的就是一共20個int
for (i = 10; i < 20; i ) {//再賦值 注意從第10個開始的
pn[i] = i;
}
for (i = 0; i < 20; i ) {//輸出
printf("=", pn[i]);
}
printf("\n");
printf("p=%p \nt=%p\n", pn, t);//輸出地址
free(pn);//釋放空間
pn = NULL;//指針指空
return 0;
}
如果申請空間的數值較小,原來申請的動态内存後面還有空餘内存,系統将直接在原内存空間後面擴容
并返回原動态空間基地址;如果申請空間的數值較大,原來申請的空間後面沒有足夠大的空間擴容,
系統将重新申請一塊新的内存,并把原來空間的内容拷貝過去,原來空間OS自動free;如果申請空間的數值非常大,
系統内存申請失敗,返回NULL,原來的内存不會釋放。注意:如果擴容後的内存空間較原空間小,将會出現數據丢失,
如果直接realloc(p, 0);相當于free(p).
使用總結:
(1)realloc失敗的時候,返回NULL
(2)realloc失敗的時候,原來的内存不改變,不會釋放也不會移動
(3)假如原來的内存後面還有足夠多剩餘内存的話,realloc的内存=原來的内存 剩餘内存,realloc還是返回原來内存的地址; 假如原來的内存後面沒有足夠多剩餘内存的話,realloc将申請新的内存,然後把原來的内存數據拷貝到新内存裡,原來的内存将被free掉,realloc返回新内存的地址
(4)如果size為0,效果等同于free()。這裡需要注意的是隻對指針本身進行釋放,例如對二維指針**a,對a調用realloc時隻會釋放一維,使用時謹防内存洩露。
(5)傳遞給realloc的指針必須是先前通過malloc(),calloc(), 或realloc()分配的
(6)傳遞給realloc的指針可以為空,等同于malloc。
malloc與free函數malloc中文叫動态内存分配,用于申請一塊連續的指定大小的内存塊區域以void*類型返回分配的内存區域地址,當無法知道内存具體位置的時候,想要綁定真正的内存空間,就需要用到動态的分配内存,且分配的大小就是程序要求的大小。
函數原型:
void * malloc(size_t size);
在以前 malloc返回的是char型指針,新的ANSIC标準規定,該函數返回為void型指針,因此必要時要進行類型轉換。
它能向系統申請分配一個長度為num_bytes(或size)個字節的内存塊。
其作用是在内存的動态存儲區中分配一個長度為size的連續空間。當函數申請内存分配成功時,
此函數的返回值是分配區域的起始地址,或者說,此函數是一個指針型函數,返回的指針指向該分配域的開頭位置。
(它返回的是分配得到的内存的首字節地址),如果無法獲得符合要求的内存塊,malloc函數會返回空指針
size為要申請的空間大小,需要我們手動的去計算,如int *p = (int * )malloc(20*sizeof(int)),如果編譯器默認int為4字節存儲的話,那麼計算結果是80 Byte,一次申請一個80 Byte的連續空間,并将空間基地址強制轉換為int類型,賦值給指針p,此時申請的内存值是不确定的。
malloc函數的實質體現在,它有一個将可用的内存塊連接為一個長長的列表的所謂 空閑鍊表的功能。
調用malloc函數時,它沿連接表尋找一個大到足以滿足用戶請求所需要的内存塊。然後,将該内存塊一分為二(一塊的大小與用戶請求的大小相等,另一塊的大小就是剩下的字節)。接下來,将分配給用戶的那塊内存傳給用戶,并将剩下的那塊(如果有的話)返回到連接表上。
調用free函數時,它将用戶釋放的内存塊連接到空閑鍊上。到最後,空閑鍊會被切成很多的小内存片段,如果這時用戶申請一個大的内存片段,那麼空閑鍊上可能沒有可以滿足用戶要求的片段了。
于是,malloc函數請求延時,并開始在空閑鍊上翻箱倒櫃地檢查各内存片段,對它們進行整理,将相鄰的小空閑塊合并成較大的内存塊。如果無法獲得符合要求的内存塊,malloc函數會返回NULL指針(空指針),因此在調用malloc動态申請内存塊時,一定要進行返回值的判斷。
#include<stdio.h>
#include <stdlib.h>
int main(void)
{
int count, *array; /*count是一個計數器,array是一個整型指針,也可以理解為指向一個整型數組的首地址*/
if ((array=(int *) malloc(10 * sizeof(int))) == NULL)//把類型強制轉換為int 申請内存空間 10個int的空間
//一個int大小是sizeof(int)
{
printf("不能成功分配存儲空間。");
exit(1); //強制結束程序
}
for (count = 0; count < 10; count ) { /*給數組賦值*/
array[count] = count;
}
for (count = 0; count < 10; count ) { /*打印數組元素*/
printf("-", array[count]);
}
return 0;
}
free函數:
free()是C語言中釋放内存空間的函數,通常與申請内存空間的函數malloc()結合使用,可以釋放由 malloc()、calloc()、realloc() 等函數申請的内存空間。
函數原型:
void free(void *ptr);
ptr-- 指針指向一個要釋放内存的内存塊,該内存塊之前是通過調用
malloc、calloc 或 realloc 進行分配内存的。如果傳遞的參數是一個空指針,則不會執行任何動作。
該函數不返回任何值。
上面的例子:
#include<stdio.h>
#include <stdlib.h>
int main(void)
{
int count, *array; /*count是一個計數器,array是一個整型指針,也可以理解為指向一個整型數組的首地址*/
if ((array=(int *) malloc(10 * sizeof(int))) == NULL)//把類型強制轉換為int 申請内存空間 10個int的空間
//一個int大小是sizeof(int)
{
printf("不能成功分配存儲空間。");
exit(1); //強制結束程序
}
for (count = 0; count < 10; count ) { /*給數組賦值*/
array[count] = count;
}
for (count = 0; count < 10; count ) { /*打印數組元素*/
printf("-", array[count]);
}
free(array); //剛剛沒有進行釋放内存
return 0;
}
******free的重要性:*******
靜态内存的數量在編譯時是固定的,在運行期間也不會改變,
自動變量使用的内存數量在程序執行期間自動增加或減少,但是動态内存分配内存的數量隻會增加,除非使用free函數進行釋放
它創建了指針array,并調用了malloc函數進行内存分配了(10* 4(int) )40個字節的内存,假設,如代碼注釋所示,
遺漏了free,當函數結束時,作為自動變量的指針array也會消失,但是它所指向的40個字節的内存卻仍然存在,
由于array指針已被銷毀,所以無法訪問這塊内存,它也不能被重複使用,因為代碼中沒有調用free函數釋放這塊内存,
如果是一個函數,當第二次調用它時,它又創建了array指針,并調用malloc分配40個字節的内存,第一次調用的40個字節的内存已不可用,
所以malloc函數分配了另外的内存,當函數結束時該内存也無法被訪問和再使用,如果循環要進行1000次,那麼每一次的調用都會分配内存,
持續增加,實際上,等不到程序結束,内存早已被耗盡,這類問題被稱為内存洩漏,所以 為防止這類問題的發生,
必須要在動态内存分配函數後加上free函數釋放内存。
總結:
malloc 必須要由我們計算字節數,并且在返回後強行轉換為實際類型的指針。另外有一點不能直接看出的區别是,malloc 隻管分配内存,并不能對所得的内存進行初始化,所以得到的一片新内存中,其值将是随機的
一般使用後要使用free(起始地址的指針) 對内存進行釋放,不然内存申請過多會導緻内存洩漏會影響計算機的性能,以至于得重啟電腦。如果使用過後不清零,還可以使用該指針對該塊内存進行訪問。
通常,malloc函數要和free函數一起配對使用,free函數的參數是之前mallloc函數返回的地址(指針),該函數釋放之前malloc函數分配的内存,因此,動态内存分配的存儲期是從動态内存分配函數malloc(或其他)到f調用ree函數釋放内存為止,涉嫌malloc和free函數管理着一個内存池。
每次調用malloc分配内存給程序使用,每次調用free函數把内存空間歸還給内存池中,這樣便可以重複使用這些内存,free函數的參數應該是一個指針,指向由malloc函數分配的一塊内存,不能用free函數釋放通過其他方式(如 :聲明一個數組),分配的内存,malloc函數和free函數的原型都在stdio.h頭文件中。
作者:Mr_Li_
另外的話為了幫助大家,輕松,高效學習C語言/C ,我給大家分享我收集的資源,從最零基礎開始的教程到C語言項目案例,幫助大家在學習C語言的道路上披荊斬棘!可以來我粉絲群領取哦~
C語言/C 編程學習視頻分享:
C語言/C 編程學習書籍分享:
整理分享(多年學習的源碼、項目實戰視頻、項目筆記,基礎入門教程)最重要的是你可以在群裡面交流提問編程問題哦!(↓↓↓↓↓)
對于C/C 感興趣可以關注小編在後台私信我:【編程交流】一起來學習哦!可以領取一些C/C 的項目學習視頻資料哦!已經設置好了關鍵詞自動回複,自動領取就好了!
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!