新四季網

c語言函數的使用學習心得(零基礎學C語言內存知識總結)

2023-11-05 06:42:51

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

#include

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

#include

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

#include

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 的項目學習視頻資料哦!已經設置好了關鍵詞自動回復,自動領取就好了!

,
同类文章
葬禮的夢想

葬禮的夢想

夢見葬禮,我得到了這個夢想,五個要素的五個要素,水火只好,主要名字在外面,職業生涯良好,一切都應該對待他人治療誠意,由於小,吉利的冬天夢想,秋天的夢是不吉利的
找到手機是什麼意思?

找到手機是什麼意思?

找到手機是什麼意思?五次選舉的五個要素是兩名士兵的跡象。與他溝通很好。這是非常財富,它擅長運作,職業是仙人的標誌。單身男人有這個夢想,主要生活可以有人幫忙
我不怎麼想?

我不怎麼想?

我做了什麼意味著看到米飯烹飪?我得到了這個夢想,五線的主要土壤,但是Tu Ke水是錢的跡象,職業生涯更加真誠。他真誠地誠實。這是豐富的,這是夏瑞的巨星
夢想你的意思是什麼?

夢想你的意思是什麼?

你是什​​麼意思夢想的夢想?夢想,主要木材的五個要素,水的跡象,主營業務,主營業務,案子應該抓住魅力,不能疏忽,春天夢想的吉利夢想夏天的夢想不幸。詢問學者夢想
拯救夢想

拯救夢想

拯救夢想什麼意思?你夢想著拯救人嗎?拯救人們的夢想有一個現實,也有夢想的主觀想像力,請參閱週宮官方網站拯救人民夢想的詳細解釋。夢想著敵人被拯救出來
2022愛方向和生日是在[質量個性]中

2022愛方向和生日是在[質量個性]中

[救生員]有人說,在出生88天之前,胎兒已經知道哪天的出生,如何有優質的個性,將走在什麼樣的愛情之旅,將與生活生活有什么生活。今天
夢想切割剪裁

夢想切割剪裁

夢想切割剪裁什麼意思?你夢想切你的手是好的嗎?夢想切割手工切割手有一個真正的影響和反應,也有夢想的主觀想像力。請參閱官方網站夢想的細節,以削減手
夢想著親人死了

夢想著親人死了

夢想著親人死了什麼意思?你夢想夢想你的親人死嗎?夢想有一個現實的影響和反應,還有夢想的主觀想像力,請參閱夢想世界夢想死亡的親屬的詳細解釋
夢想搶劫

夢想搶劫

夢想搶劫什麼意思?你夢想搶劫嗎?夢想著搶劫有一個現實的影響和反應,也有夢想的主觀想像力,請參閱週恭吉夢官方網站的詳細解釋。夢想搶劫
夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂什麼意思?你夢想缺乏異常藥物嗎?夢想缺乏現實世界的影響和現實,還有夢想的主觀想像,請看官方網站的夢想組織缺乏異常藥物。我覺得有些東西缺失了