C語言動(dòng)態(tài)開辟內(nèi)存詳解
1.動(dòng)態(tài)內(nèi)存管理
我們已經(jīng)掌握的內(nèi)存開辟方法,用的最多的就是數(shù)組,但是首先我們知道數(shù)組實(shí)在棧上開辟空間的,要是我們開辟大量的空間怎么辦呢?而且我不確定數(shù)據(jù)的大小萬一造成內(nèi)存資源浪費(fèi)是不是也不劃算呢?所以我認(rèn)為一下兩點(diǎn)就很充分的說明動(dòng)態(tài)開辟內(nèi)存存在的必要性。
1.一般方式(棧上開辟)只能自動(dòng)開辟少量的空間,但是堆上可以開辟大量的空間。
2.對(duì)于不定長數(shù)據(jù)保存問題,動(dòng)態(tài)開辟空間可以解決。
2.動(dòng)態(tài)開辟內(nèi)存函數(shù)的介紹
2.1 malloc和free函數(shù)
C語言提供了一個(gè)動(dòng)態(tài)開辟內(nèi)存的函數(shù)。
void* malloc (size_t size);
C語言還提供了一個(gè)函數(shù)free是對(duì)動(dòng)態(tài)開辟內(nèi)存釋放和回收的。
void free (void* ptr);
這兩個(gè)函數(shù)都聲明在stdlib.h這個(gè)頭文件中
那如何進(jìn)行內(nèi)存的開辟與釋放呢?舉個(gè)例子。
int main() {
int* p = (int*)malloc(10 * sizeof(int));
if (NULL == p) {
return 1;
}
free(p);
}1.malloc 等空間申請(qǐng)都是在堆上進(jìn)行申請(qǐng),最后必須由free來進(jìn)行釋放。堆上的空間是由程序員自己管理。
2.malloc是一個(gè)函數(shù),表明了堆空間說在程序運(yùn)行起來之后,再在系統(tǒng)上申請(qǐng)的,空間只申請(qǐng)不釋放,會(huì)造成內(nèi)存泄露問題!
3.那free是做了什么呢?他是把開辟的空間給清除了?還是把指針給清空了?
其實(shí)都不是,free做的是取消了指針和所對(duì)應(yīng)內(nèi)存的指向 “關(guān)系”。
在實(shí)際申請(qǐng)空間的時(shí)候,真實(shí)給你的空間是要大于你所需要的,但是你只能使用你要的大小,多出來的字節(jié),用來維護(hù)剛剛說的那種關(guān)系,以及保存該次申請(qǐng)的 元數(shù)據(jù)(屬性數(shù)據(jù)):用戶申請(qǐng)的空間有多大,所以在free傳參的時(shí)候只用傳入你開辟空間的起始地址就好了,根據(jù)屬性數(shù)據(jù)free函數(shù)就知道該釋放多少空間。
4.那我不想釋放那么多可以嗎?我按照以下代碼free。
free(p+4);
是不行的!堆空間必須整體申請(qǐng)整體釋放。
2.2 calloc函數(shù)
C語言還提供了一個(gè)函數(shù)calloc
void* calloc(size_t num, size_t size );
calloc跟malloc使用基本一樣


只是有一點(diǎn)區(qū)別,malloc沒做初始化,隨機(jī)值,malloc效率更高一點(diǎn)。calloc做了初始化,效率更低一點(diǎn)。
2.3 relloc函數(shù)
C語言提供的這個(gè)函數(shù)讓動(dòng)態(tài)內(nèi)存管理更加的靈活,有時(shí)候發(fā)現(xiàn)申請(qǐng)的空間太小了,有時(shí)候覺得申請(qǐng)的空間太大了,合理調(diào)整內(nèi)存就有了relloc函數(shù)。
void* relloc (void* ptr,size_t size);
ptr是調(diào)整內(nèi)存的地址,size是調(diào)整后的大小,返回值是調(diào)整之后內(nèi)存的起始地址。
一般relloc在調(diào)整內(nèi)存是存在兩種情況
1.原有空間后面有足夠大的空間

直接向后擴(kuò)充就好了
2.原有空間后面沒有足夠大的空間

所以說ptr也就是堆空間的起始地址有可能是變化的!
最后在分享一個(gè)題
void GetMemory(char* p)
{
p = (char*)malloc(100);
}
int main ()
{
char* str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}這個(gè)打印的是啥呢?
其實(shí)是有錯(cuò)誤的 str傳入函數(shù)發(fā)生臨時(shí)拷貝問題此時(shí)p和str不是一個(gè)東西進(jìn)行動(dòng)態(tài)內(nèi)存開辟讓我們的p指向開辟的空間,調(diào)用函數(shù)開辟棧幀,調(diào)用完畢釋放棧幀,p是一個(gè)臨時(shí)變量于那個(gè)空間已經(jīng)沒有指向關(guān)系了,而str依舊是NULL
更改如下
void GetMemory(char** p)
{
*p = (char*)malloc(100);
}
int main()
{
char* str = NULL;
GetMemory(&str);
strcpy(str, "hello world");
printf(str);
}總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
基于OpenCV和C++ 實(shí)現(xiàn)圖片旋轉(zhuǎn)
這篇文章主要介紹了基于OpenCV和C++ 實(shí)現(xiàn)圖片旋轉(zhuǎn),幫助大家更好的利用c++處理圖片,感興趣的朋友可以了解下2020-12-12
剖析C++編程中friend關(guān)鍵字所修飾的友元函數(shù)和友元類
這篇文章主要介紹了剖析C++編程中friend關(guān)鍵字所修飾的友元函數(shù)和友元類,友元了以后在外部就可以訪問到正常情況下無法訪問到的私有屬性和方法,需要的朋友可以參考下2016-01-01
C語言數(shù)據(jù)結(jié)構(gòu)不掛科指南之線性表詳解
線性表是由?n(n≥0)個(gè)數(shù)據(jù)元素組成的有窮序列,這篇文章主要來和大家來了C語言數(shù)據(jù)結(jié)構(gòu)中的線性表,感興趣的小伙伴可以跟隨小編一起了解一下2022-09-09
C++ operator關(guān)鍵字(重載操作符)的用法詳解
下面小編就為大家?guī)硪黄狢++ operator關(guān)鍵字(重載操作符)的用法詳解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-01-01

