首頁 > 軟體

深入瞭解C語言中的動態記憶體分配

2022-06-29 22:02:07

今天我們來學習一下C語言中的動態記憶體分配 開始學習吧

什麼是動態記憶體分配

我們目前已經知道的記憶體開闢的方式有:

int val = 20;//在棧上開闢四個位元組。
char arr[10]  = { 0 };//在棧上開闢十個位元組的連續空間

但是上述空間的開闢方式有兩個特點:

1.空間開闢的大小是固定的

2.陣列在申明的時候,必須指定陣列長度,它所需記憶體在編譯時分配。

顯然,這樣無法滿足有些場景的要求,有時我們所需要的空間大小隻有在程式執行的時候才知道。這時我們就需要用到動態記憶體分配了。

如何進行動態記憶體分配

首先我要介紹兩個函數 malloc 和 free

void* malloc(size_t size);

這個函數向記憶體申請一塊連續可用的空間,並返回指向這塊空間的指標。

  • 如果開闢成功,則返回一個指向開闢好空間的指標。
  • 如果開闢失敗,則返回一個NULL指標,因此malloc的返回值一定要做檢查。
  • 返回值的型別是void*,所以malloc函數並不知道開闢空間的型別,具體在使用的時候由使用者來決定
  • 如果引數size為0,malloc的行為是標準未定義的,取決於編譯器。

現在我們知道了如何去開闢空間,接下來,我們去學習一下如何將開闢的空間釋放掉。

void free(void* ptr);

C語言提供了另外一個函數free是專門用來釋放動態記憶體的

  • 如果引數ptr指向的空間不是動態記憶體開闢的,那麼free的行為是未定義的。
  • 如果引數ptr是NULL指標,那麼函數什麼都不會做。

想使用malloc 和 free 都需要引入一個標頭檔案<stdlib.h>

接下來讓我們看個範例:

#include <stdlib.h>
#include <stdio.h>

int main()
{
    int num = 0;
    scanf("%d", &num);
    int *ptr = (int*)malloc(sizeof(int) * num);
    //判斷是否開闢成功
    if(NULL != ptr)
    {
        int i = 0;
        for(i = 0; i < num; i++)
        {
            *(ptr + i) = 0;
        }
    }
    free(ptr);//釋放空間
    ptr = NULL;
    return 0;
}

第二個開闢空間的動態記憶體分配的函數 calloc

void* calloc(size_t num, size_t size);

函數的功能是為num個大小為size的元素開闢一塊空間,並且把空間的每個位元組都初始化為0

malloc與calloc的區別在於calloc會在返回地址之前把申請的空間的每個位元組都初始化為0

舉個例子:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int *p = (int*)calloc(10, sizeof(int));
    if(NULL != p)
    {
        int i = 0;
        for(i = 0; i < 10; i++)
        {
            *(ptr + i) = 0;
        }
    }
    free(p);
    p = NULL;
    retrun 0;
}

所以如果我們對申請的記憶體空間的內容要求初始化,那麼可以很方便的使用calloc函數來完成任務。

大小修改函數realloc

有時候我們會發現之前申請的空間太小,有時又會覺得申請的空間過大,那為了合理的使用記憶體,我們一定會對記憶體的大小做靈活調整。realloch函數就可以對動態開闢的記憶體大小進行調整

void* realloc(void* ptr, size_t size);
  • ptr 是要調整的記憶體地址
  • size 調整之後的新大小
  • realloc在調整記憶體空間後的返回值有兩種情況

情況一:原有空間之後有足夠大的空間,要擴充套件記憶體就直接在原有記憶體之後追加空間,原有空間的資料不變。

情況二:原有空間之後無足夠大的空間,擴充套件方法是在堆上另找一塊連續的空間來使用,這樣函數返回的就是一個新的記憶體地址

以上就是深入瞭解C語言中的動態記憶體分配的詳細內容,更多關於C語言 動態記憶體分配的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com