陣列的元素儲存與記憶體中連續的位置,當乙個陣列被宣告時,它所需要的內存在編譯時就被分配,但是我們也可以用動態記憶體分配在執行時為它分配記憶體。
c語言庫函式提供了兩個函式,malloc和free,分別用於執行動態記憶體分配和釋放。這些函式維護乙個可用的記憶體池。
當程式設計師需要一些記憶體時,呼叫malloc函式,malloc從記憶體中提取一塊合適的記憶體,並向該程式返回乙個指向這塊記憶體的指標。
這塊記憶體此時並沒有以任何方式進行初始化,如果需要對這塊記憶體進行初始化,要麼手動進行初始化,要麼使用calloc函式。當申請的記憶體不再使用時,程式呼叫free函式把它歸還給記憶體池。
這兩個函式的宣告如下所示:
void* malloc(size_t size);
void* free(void* pointer);
malloc的引數就是需要分配的位元組數,如果記憶體池中的可用記憶體可以滿足這個需求,malloc就返回乙個指向被分配的記憶體塊起始位置的指標。
malloc分配一塊連續的記憶體,所以如果記憶體池不夠你需要分配的記憶體,它會返回乙個null指標,所以對每個從malloc返回的指標都進行檢查是非常有必要的。
free的引數要麼是null,要麼是乙個先前從malloc,calloc或realloc返回的值,向free傳遞乙個null引數並不i產生任何後果。
malloc返回乙個void*的指標,標準規定乙個void*型別的指標可以轉換為其他任何型別的指標,但是有些老式的編譯器可能需要在轉換時進行強制的型別轉換。
這兩個函式的原型如下:
void* calloc(size_t num_elements,
size_t element_size);
void* realloc(void* ptr, size_t new_size);
calloc也是用於分配記憶體的函式。malloc和calloc之間的區別是,後者在返回指標之前把它初始化為0.這個初始化常常能帶來方便,但是如果只是把一些值存入到陣列,那麼純粹是在浪費時間。
calloc和malloc函式的另乙個區別是他們請求記憶體數量的方式不同。calloc的引數包括所需元素的數量和每個元素的位元組數。根據這些值,它能夠計算出總共需要分配的記憶體。
realloc函式用於修改乙個原先已經分配的記憶體塊的大小,使用這個函式,可以使一塊記憶體進行擴大或者縮小,如果它用於擴大一塊記憶體塊,那麼這塊記憶體原先的內容依然保留,新增加的記憶體新增到原先記憶體塊的後面,新記憶體並未以任何方法進行初始化。如果它用於縮小乙個記憶體塊,該記憶體塊尾部的部分記憶體被拿掉,剩餘部分記憶體的原先內容依舊保留。
注意:如果原先的記憶體塊無法改變大小,realloc將分配另一塊正確大小的記憶體,並把原先那塊記憶體的內容複製到新的塊上。所以,使用realloc之前,不能再使用指向舊記憶體的指標,而是應該改用realloc所返回的新指標。
用malloc分配記憶體的例子:
pi = malloc(100);
if(pi == null)
如果記憶體分配成功,就能得到乙個指向100個位元組的指標。
但是,如果你的目標就是獲得足夠儲存25個整數的記憶體,有乙個更好的方法:
pi = (int*)malloc( 25 * sizeof(int) );
這樣做的話可移植性更高
在動態記憶體分配的程式中,會出現許多常見的錯誤。
這些錯誤包括,1.對null指標進行解引用操作,2.對分配的記憶體進行操作時越過邊界,3.釋放並非動態記憶體分配的記憶體,4.試圖釋放一塊動態記憶體的記憶體的一部分以及5.一塊動態記憶體被釋放之後繼續被使用。
動態記憶體分配最常見的錯誤就是忘記檢查所請求的記憶體是否成功分配。
傳給free函式乙個指標,讓它釋放一塊並非動態記憶體分配的記憶體可能導致程式立即終止或者在晚些時候終止。
不要訪問已經被free函式釋放了的記憶體。
動態記憶體分配中,一種很嚴重的錯誤就是記憶體洩漏
當動態分配的記憶體不再需要使用時,它就應該被釋放,這樣它以後可以被重新分配使用,但是如果在使用完畢後不再釋放就將引起記憶體洩漏。
當陣列被宣告時,必須在編譯時知道它的長度,動態記憶體分配允許程式為乙個長度在執行時才知道的陣列分配記憶體空間。
malloc和calloc函式都用於分配一塊記憶體,並返回乙個指向該記憶體空間的指標。malloc函式的引數就是需要分配的記憶體的位元組數,calloc函式的引數是你需要分配的元素個數和每個元素的長度。calloc函式在返回前把記憶體初始化為0,而malloc函式並沒有以任何形式對分配的記憶體進行初始化。
呼叫realloc函式可以改變一塊已經分配的記憶體的大小,增加記憶體塊大小時有可能採取的方法是把原來記憶體塊上的所有資料複製到乙個新的更大的記憶體塊上。當乙個動態分配的記憶體不再使用時應該使用free函式釋放,被釋放的記憶體不能再被訪問。如果請求的記憶體分配失敗,這三個函式都將返回乙個null指標,錯誤的訪問記憶體分配之外的元素導致的後果類似陣列越界訪問,但是這個錯誤還可能破壞記憶體池導致程式失敗。
1.不檢查從malloc函式返回的指標是否為null指標
2.訪問動態分配的記憶體之外的記憶體
3.向free函式傳遞乙個並非由malloc函式返回的指標
4.在動態記憶體被釋放之後再訪問它
c語言動態記憶體分配 C 動態記憶體分配
動態記憶體分配 雖然通過陣列就可以對大量的資料和物件進行有效地管理,但是很多情況下,在程式執行之前,我們並不能確切地知道陣列中會有多少個元素。這種情況下,如果陣列宣告過大,就會造成浪費 宣告過小,就會影響處理。在c 中,動態記憶體分配技術可以保證程式在執行過程中按照需要申請適量記憶體,使用後釋放,從...
C語言 動態記憶體分配總結
3 memset 4 realloc void malloc unsigned int num bytes 分配長度為num bytes個位元組的記憶體塊,返回值為無型別指標,該指標指向所分配記憶體塊的起始位置,因此利用該無型別指標賦值給其他型別的指標的時候,需要進行強制型別轉換。int p int...
C語言動態記憶體分配
c語言動態記憶體分配 動態資料結構可以在執行時靈活新增 刪除或重排資料項。在執行時分配記憶體空間的過程稱為動態記憶體分配。記憶體分配函式如下 malloc 分配所需的位元組大小,並返回指向所分配空間的第乙個位元組的指標 calloc 為元素陣列分配空間,並初始化為零,然後返回指向該記憶體的指標 fr...