为什么需要动态内存分配?
傳統(tǒng)數(shù)組的缺點(diǎn):
1,數(shù)組的長(zhǎng)度必須實(shí)現(xiàn)預(yù)定,且是常整數(shù),不能是變量,
例如:
? ? ? ? ?int?a[5];? ?//正確
? ? ? ? ?int? len=5;? int a[len];? ?//error
2,傳統(tǒng)形式定義的數(shù)組,該數(shù)組內(nèi)存程序員無法手動(dòng)釋放,在一個(gè)函數(shù)運(yùn)行期間,系統(tǒng)為該函數(shù)中的數(shù)組所分配的空間會(huì)一直存在,直到該函數(shù)運(yùn)行完畢,數(shù)組的空間才會(huì)被系統(tǒng)釋放。
3,數(shù)組的長(zhǎng)度不能在函數(shù)程序運(yùn)行的過程中動(dòng)態(tài)的擴(kuò)充或縮小(長(zhǎng)度定義之后就不能變化)
4,A函數(shù)定義的數(shù)組,在A函數(shù)運(yùn)行期間可以被其他函數(shù)使用,但是A函數(shù)運(yùn)行完畢之后,A函數(shù)中的數(shù)組將無法在被其他函數(shù)使用
傳統(tǒng)型定義的數(shù)組無法跨函數(shù)使用(在一個(gè)函數(shù)內(nèi)部定義的數(shù)組這個(gè)函數(shù)運(yùn)行結(jié)束之后就釋放了)
void g(int * pArr, int length) {pArr[2] = 88; //通過指針改變數(shù)組的值 }void function(void) {int a[5] = { 1,2,3,4,5 };g(a, 5); //調(diào)用g(a,5)函數(shù)printf("%d\n", a[2]); }int main() {char ch = 'A';int i = 99;double x = 66.6;char *p = &ch;int *q = &i;double *r = &x; /*一個(gè)指針占用四個(gè)字節(jié)具體參考上一篇文章:https://blog.csdn.net/ywl470812087/article/details/103380837*/ // printf("%d %d %d", sizeof(p), sizeof(q), sizeof(r)); //4 4 4function(); //調(diào)研function()while (true){}}?
為什么需要?jiǎng)討B(tài)內(nèi)存分配?
我講解一下c語言中動(dòng)態(tài)分配內(nèi)存的函數(shù),可能有些初學(xué)c語言的人不免要問了:我們?yōu)槭裁匆ㄟ^函數(shù)來實(shí)現(xiàn)動(dòng)態(tài)分配內(nèi)存呢?系統(tǒng)難道不是會(huì)自動(dòng)分配內(nèi)存嗎??
既然有人會(huì)問這樣的問題,那么我在這里好好的講解一下吧!
首先讓我們熟悉一下計(jì)算機(jī)的內(nèi)存吧!在計(jì)算機(jī)的系統(tǒng)中有四個(gè)內(nèi)存區(qū)域:
1)棧:在棧里面儲(chǔ)存一些我們定義的局部變量以及形參(形式參數(shù));
2)字符常量區(qū):主要是儲(chǔ)存一些字符常量,比如:char *p_str=”cgat”;其中”cgat”就儲(chǔ)存在字符常量區(qū)里面;?
3)全局區(qū):在全局區(qū)里儲(chǔ)存一些全局變量和靜態(tài)變量;
4)堆:堆主要是通過動(dòng)態(tài)分配的儲(chǔ)存空間,也就是我們接下需要講的動(dòng)態(tài)分配內(nèi)存空間。
什么時(shí)候我們需要?jiǎng)討B(tài)分配內(nèi)存空間呢?
舉一個(gè)例子吧。
int *p; 我們定義了一個(gè)指向int類型的指針p;p是用來儲(chǔ)存一個(gè)地址的值的,我們之所以要為p這個(gè)變量分配空間是讓它有一個(gè)明確的指向,打個(gè)比方吧!你現(xiàn)在做好了一個(gè)指向方向的路標(biāo),但是你并沒有讓這個(gè)路標(biāo)指向一個(gè)確切的方位,也就是說現(xiàn)在的這個(gè)路標(biāo)是瞎指向的,這樣我們就不能夠通過它來明確到底哪里是東,哪里是西,何為北,何為南了。雖然我們?cè)谟?jì)算機(jī)的內(nèi)存里定義了一個(gè)指針變量,但是我們并沒有讓這個(gè)變量指示一個(gè)確切int類型變量的地址,所以我們就必須要讓它有一個(gè)明確的指示方向。這樣我們就要通過動(dòng)態(tài)分配內(nèi)存的方式來認(rèn)為的規(guī)定它的方向!我們?cè)趧倓偨佑|指針的時(shí)候遇到過這樣的情況,
int *p;p=&a;這種方法不是指針的動(dòng)態(tài)分配內(nèi)存,這個(gè)叫做指針變量的初始化!初始化同樣也可以讓指針變量有方向可指。
int *p;p=malloc(n*sizeof(類型名稱));我們通過malloc()函數(shù)為一個(gè)指針變量p分配了地址,這樣我們從鍵盤上鍵入的值就這樣存儲(chǔ)在p里面了,接下來我們就可以對(duì)這個(gè)p進(jìn)行具體的操作了,比如scanf(“%s”,p)等等。當(dāng)我們對(duì)p結(jié)束操作的時(shí)候還要釋放p的內(nèi)存空間。
為什么要釋放內(nèi)存空間呢?
在上面我已經(jīng)講過動(dòng)態(tài)分配的變量時(shí)儲(chǔ)存在堆里面,但是這個(gè)堆的空間并不是無限大的,也許當(dāng)我們編一個(gè)小的程序的時(shí)候可能我們并不能夠發(fā)現(xiàn)什么,但是對(duì)于那些大的程序,如果我們不及時(shí)釋放堆的空間的時(shí)候會(huì)發(fā)生內(nèi)存泄露。所謂內(nèi)存泄露是因?yàn)槎训目臻g把我們動(dòng)態(tài)分配用完了,這樣當(dāng)我們?cè)偃ナ褂脛?dòng)態(tài)分配堆的空間的時(shí)候就沒有足夠的空間讓我們使用了,這樣就需要占有原來的空間,也就是會(huì)把其他的空間來儲(chǔ)存我們鍵入的值,這樣會(huì)導(dǎo)致原來儲(chǔ)存的數(shù)據(jù)被破壞掉,導(dǎo)致了內(nèi)存的泄露了。
同時(shí)當(dāng)我們使用malloc()函數(shù)的時(shí)候還應(yīng)該注意當(dāng)我們釋放完空間的時(shí)候還要將原先的指針變量賦予一個(gè)NULL,也就是賦予一個(gè)空指針,留著下次的時(shí)候使用它!
如果我們不賦予|NULL行不行呢??
答案是:不行的!如果我們不賦予一個(gè)空指針這樣會(huì)導(dǎo)致原先的指針變量成為了一個(gè)野指針!何謂野指針?野指針就是一個(gè)沒有明確指向的指針,系統(tǒng)不知道它會(huì)指向什么地方,野指針是很危險(xiǎn)的,因此當(dāng)我們每次使用完malloc()函數(shù)的時(shí)候都必須將指針賦予一個(gè)空指針!相對(duì)于malloc()函數(shù),calloc()函數(shù)就不需要我們賦予NULL了,這是因?yàn)樵诿看握{(diào)用完calloc()函數(shù)的時(shí)候系統(tǒng)會(huì)自動(dòng)將原先的指針賦予一個(gè)空指針,即歸于“0”。calloc()函數(shù)的原型是void *calloc(count,sizeof(類型名稱));
比如:p=(char*)calloc(4,sizeof(char));我們?yōu)閜分配了指向char型指針的“4”個(gè)空間。
除了malloc()與calloc(),還有一個(gè)動(dòng)態(tài)分配空間的函數(shù)realloc()函數(shù),
這個(gè)函數(shù)比前兩個(gè)函數(shù)分配更多的空間,原型:void *realloc(void *p,size_t?size);
該函數(shù)有幾個(gè)作用:
1)??? 如果有足夠的空間來擴(kuò)充p的內(nèi)存塊,則返回一個(gè)指向p的指針;
2)??? 如果沒有足夠的空間來擴(kuò)充p的內(nèi)存塊,則為p從新分配size的空間,并把原來的內(nèi)容復(fù)制給p,指向p的開頭,同時(shí)釋放原來的空間,返回一個(gè)指向新內(nèi)存塊的指針;
3)??? 如果p=NULL,其作用于malloc()相似;
?
下面舉一個(gè)程序的例子: #define LONG 10 #include<string.h> #include<stdlib.h> #include<stdio.h> main() {char *message,buf[LONG];gets(buf);message=(char*)realloc(NULL,strlen(buf)+1);strcpy(message,buf);puts(message);gets(buf);message=(char*)realloc(message,(strlen(message)+strlen(buf)+1));strcat(message,buf);puts(message);return 0; }?
當(dāng)你不確定內(nèi)存空間大小的時(shí)候。。有2種辦法。
1。預(yù)先定義一個(gè)足夠大的空間。(這個(gè)比較浪費(fèi)資源。而且隨著程序的使用推廣。預(yù)先定義的空間也不一定能完全滿足條件)
2。動(dòng)態(tài)的分配內(nèi)存??梢宰龅綔?zhǔn)確分配空間大小。不浪費(fèi)資源,而且也不會(huì)發(fā)生程序不斷使用預(yù)先分配內(nèi)存不足。
備注:動(dòng)態(tài)分配的內(nèi)存空間系統(tǒng)不負(fù)責(zé)自動(dòng)回收,需要寫代碼手動(dòng)釋放。
總結(jié)
以上是生活随笔為你收集整理的为什么需要动态内存分配?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 快速幂模板~
- 下一篇: zcmu-1931(dfs方格切割)