C語言記憶體管理



C語言的一個重要特性是編譯器管理程式碼中宣告的變數的記憶體分配方式。一旦編譯器分配了所需的記憶體位元組,在執行時就無法更改。

編譯器採用靜態記憶體分配方法。但是,有時您可能需要在執行時按需分配記憶體。閱讀本章以瞭解C語言中的動態記憶體管理是如何工作的。

C語言中動態記憶體管理的函式

C程式語言提供了一些用於動態記憶體分配和管理的函式。這些函式可以在<stdlib.h>標頭檔案中找到。

函式 描述
void *calloc(int num, int size); 此函式分配一個包含num個元素的陣列,每個元素的大小(以位元組為單位)為size。
void free(void *address); 此函式釋放由address指定的記憶體塊。
void *malloc(size_t size); 此函式分配一個包含num個位元組的陣列,並將其保留為未初始化狀態。
void *realloc(void *address, int newsize); 此函式重新分配記憶體,將其擴充套件到newsize。

動態分配記憶體

如果您知道陣列的大小,那麼很容易定義它為一個數組。例如,如果您需要儲存一個人的姓名,那麼您可以安全地定義一個數組來儲存最多100個字元(假設姓名不會超過100個字元)。因此,您可以按如下方式定義一個數組:

char name[100];

這是一個靜態記憶體分配的例子。現在讓我們考慮一種情況,您不知道需要儲存的文字的長度,例如,您想儲存有關某個主題的詳細說明。在這種情況下,如果內容少於分配的大小,則在程式執行期間分配的記憶體會被浪費。

另一方面,如果所需的大小超過分配的記憶體大小,則可能導致不可預測的行為,包括導致資料損壞,因為陣列的大小無法動態更改。

在這種情況下,您需要使用本章中描述的動態記憶體分配方法。

malloc() 函式

此函式在stdlib.h標頭檔案中定義。它分配一個所需大小的記憶體塊,並返回一個void指標

void *malloc (size)

size引數指的是以位元組為單位的記憶體塊。要為指定的 資料型別分配記憶體,您需要使用型別強制轉換運算子。

例如,以下程式碼片段分配了儲存int型別所需的記憶體:

int *ptr;
ptr = (int *) malloc (sizeof (int));

在這裡,我們需要定義一個指向字元的指標,而無需定義需要多少記憶體,然後根據需要分配記憶體。

示例

以下示例使用malloc()函式分配儲存字串所需的記憶體(而不是宣告固定大小的char陣列):

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

int main() {

   char *name;
   name = (char *) malloc(strlen("TutorialsPoint"));
   strcpy(name, "TutorialsPoint");

   if(name  == NULL) {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   } else {
      printf("Name = %s\n", name);
   }
}

輸出

當以上程式碼編譯並執行時,會產生以下輸出:

Name = TutorialsPoint

calloc() 函式

calloc()函式(代表連續分配)分配請求的記憶體並返回指向它的指標。

void *calloc(n, size);

這裡,“n”是要分配的元素數量,“size”是每個元素的位元組大小。

以下程式碼片段分配了儲存10個int型別所需的記憶體:

int *ptr;
ptr = (int *) calloc(25, sizeof(int));

示例

讓我們使用calloc()函式重寫以上程式。您只需將malloc替換為calloc即可:

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

int main() {

   char *name;
   name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char));
   strcpy(name, "TutorialsPoint");

   if(name  == NULL) {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   } else {
      printf("Name = %s\n", name);
   }
}

因此,您可以完全控制,並且可以在分配記憶體時傳遞任何大小值,這與陣列不同,陣列一旦定義了大小,就不能更改。

調整記憶體大小和釋放記憶體

當您的程式退出時,作業系統會自動釋放程式分配的所有記憶體。但是,當您不再需要使用分配的記憶體時,最好透過呼叫free()函式顯式釋放分配的記憶體,這是一個良好的實踐。

在本節中,我們將重點介紹兩個函式realloc()free()的使用,您可以使用它們來調整記憶體大小和釋放分配的記憶體。

realloc() 函式

C語言中的realloc()(重新分配)函式用於動態更改先前分配的記憶體的記憶體分配。您可以透過呼叫realloc()函式來增加或減少已分配記憶體塊的大小。

使用realloc()函式的原型如下:

void *realloc(*ptr, size);

這裡,第一個引數“ptr”是指向以前使用malloc、calloc或realloc分配的記憶體塊的指標,該記憶體塊將被重新分配。如果它是NULL,則會分配一個新的塊,並且函式會返回指向它的指標。

第二個引數“size”是以位元組為單位的新記憶體塊大小。如果它是“0”並且ptr指向現有的記憶體塊,則ptr指向的記憶體塊將被釋放,並返回一個NULL指標

示例

以下示例演示瞭如何在C程式中使用realloc()函式:

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

int main() {

   char *name;
   name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char));
   strcpy(name, "TutorialsPoint");

   name = (char *) realloc(name, strlen(" India Private Limited"));
   strcat(name, " India Private Limited");


   if(name == NULL) {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   } else {
      printf("Name = %s\n", name);
   }
}

輸出

當以上程式碼編譯並執行時,會產生以下輸出:

Name = TutorialsPoint India Private Limited

free() 函式

C語言中的free()函式用於動態釋放使用諸如malloc()和calloc()等函式分配的記憶體,因為它們不會自行釋放。

在C程式設計中,任何對未使用的記憶體的引用都會產生垃圾堆積,這可能導致程式崩潰等問題。因此,明智的做法是使用free()函式對分配的記憶體執行手動清理操作。

以下是使用free()函式的原型:

void free(void *ptr);

其中ptr是指向先前分配的記憶體塊的指標。

示例

以下示例演示瞭如何在C程式中使用free()函式:

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

int main() {

   char *name;
   name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char));
   strcpy(name, "TutorialsPoint");

   if(name  == NULL) {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   } else {
      printf("Name = %s\n", name);
      free(name);
   }
}

輸出

在程式碼的末尾,分配給char *指標的記憶體被釋放。

Name = TutorialsPoint India Private Limited
廣告