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