選單
×
   ❮   
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS R TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI GO KOTLIN SASS VUE DSA GEN AI SCIPY AWS CYBERSECURITY DATA SCIENCE
     ❯   

C 記憶體管理示例


真實記憶體管理示例

為了演示一個實際的動態記憶體示例,我們建立了一個可以生成任意長度列表的程式。

C 語言中的常規陣列長度固定且不可更改,但使用動態記憶體,我們可以建立任意長度的列表。

示例

struct list {
  int *data; // 指向儲存列表項的記憶體
  int numItems; // 指示列表中當前有多少項
  int size; // 指示已分配的記憶體可以容納多少項
};

void addToList(struct list *myList, int item);

int main() {
  struct list myList;
  int amount;

  // 建立一個列表,初始容量為 10 項
  myList.numItems = 0;
  myList.size = 10;
  myList.data = malloc(myList.size * sizeof(int));

  // 檢查記憶體分配是否成功
  if (myList.data == NULL) {
    printf("記憶體分配失敗");
    return 1; // 以錯誤程式碼退出程式
  }

  // 將 amount 變數指定的任意數量的項新增到列表中
  amount = 44;
  for (int i = 0; i < amount; i++) {
    addToList(&myList, i + 1);
  }

  // 顯示列表內容
  for (int j = 0; j < myList.numItems; j++) {
    printf("%d ", myList.data[j]);
  }

  // 在不再需要時釋放記憶體
  free(myList.data);
  myList.data = NULL;

  return 0;
}

// 此函式向列表中新增一項
void addToList(struct list *myList, int item) {

  // 如果列表已滿,則重新分配記憶體以容納另外 10 項
  if (myList->numItems == myList->size) {
    myList->size += 10;
    myList->data = realloc( myList->data, myList->size * sizeof(int) );
  }

  // 將項新增到列表末尾
  myList->data[myList->numItems] = item;
  myList->numItems++;
}
自己動手試一試 »

指向結構的指標:此示例有一個指向結構 myList 的指標。因為我們使用的是指向結構的指標而不是結構本身,所以我們使用箭頭語法 (->) 來訪問結構的成員。

示例說明

此示例包含三個部分:

  • 一個包含列表資料的 myList 結構
  • main() 函式,其中包含程式程式碼。
  • 一個 addToList() 函式,用於向列表中新增一項

myList 結構

myList 結構包含列表的所有資訊,包括其內容。它有三個成員:

  • data - 指向包含列表內容的動態記憶體的指標
  • numItems - 指示列表中的項數
  • size - 指示已分配記憶體可以容納多少項

我們使用結構是為了方便地將所有這些資訊傳遞給函式。

main() 函式

main() 函式首先初始化列表,為其分配 10 個項的空間。

// 建立一個列表,初始容量為 10 項
myList.numItems = 0;
myList.size = 10;
myList.data = malloc(myList.size * sizeof(int));

myList.numItems 設定為 0,因為列表一開始是空的。

myList.size 用於跟蹤已保留多少記憶體。我們將其設定為 10,因為我們將為 10 個項保留足夠的記憶體。

然後我們分配記憶體,並將其指標儲存在 myList.data 中。

接著,我們包含錯誤檢查,以確定記憶體分配是否成功。

// 檢查記憶體分配是否成功
if (myList.data == NULL) {
  printf("記憶體分配失敗");
  return 1; // 以錯誤程式碼退出程式
}

如果一切正常,一個迴圈將使用 addToList() 函式將 44 個項新增到列表中。

// 將 amount 變數指定的任意數量的項新增到列表中
amount = 44;
for (int i = 0; i < amount; i++) {
  addToList(&myList, i + 1);
}

在上面的程式碼中,&myList 是列表的指標,i + 1 是我們要新增到列表中的數字。我們選擇 i + 1 是為了讓列表從 1 開始而不是從 0 開始。您可以選擇任何數字新增到列表中。

在所有項都新增到列表後,下一個迴圈將列印列表的內容。

// 顯示列表內容
for (int j = 0; j < myList.numItems; j++) {
  printf("%d ", myList.data[j]);
}

在列印完列表後,我們釋放記憶體以防止記憶體洩漏。

// 在不再需要時釋放記憶體
free(myList.data);
myList.data = NULL;

addToList() 函式

我們的 addToList() 函式將一個項新增到列表中。它接受兩個引數:

void addToList(struct list *myList, int item)
  1. 指向列表的指標。
  2. 要新增到列表的值。

該函式首先透過比較列表中項的數量和列表的大小來檢查列表是否已滿。如果列表已滿,則重新分配記憶體以容納另外 10 項。

// 如果列表已滿,則重新分配記憶體以容納另外 10 項
if (myList->numItems == myList->size) {
  myList->size += 10;
  myList->data = realloc( myList->data, myList->size * sizeof(int) );
}

最後,該函式將項新增到列表末尾。myList->numItems 處的索引始終位於列表末尾,因為它在每次新增新項時會增加 1。

// 將項新增到列表末尾
myList->data[myList->numItems] = item;
myList->numItems++;

我們為什麼一次預留 10 個專案?

最佳化是一個在記憶體和效能之間取得平衡的挑戰。儘管我們可能會分配一些未使用但已分配的記憶體,但過於頻繁地重新分配記憶體會效率低下。需要在分配過多記憶體和過於頻繁分配記憶體之間找到平衡。

我們為這個示例選擇了數字 10,但這取決於您預計有多少資料以及資料更改的頻率。例如,如果我們事先知道我們將有正好 44 個項,那麼我們可以分配正好 44 個項的記憶體,並且只分配一次。


完整的 stdlib 參考

有關記憶體管理函式和標準庫中其他函式的完整參考,請訪問我們的 C <stdlib.h> 庫參考



×

聯絡銷售

如果您想將 W3Schools 服務用於教育機構、團隊或企業,請傳送電子郵件給我們
sales@w3schools.com

報告錯誤

如果您想報告錯誤,或想提出建議,請傳送電子郵件給我們
help@w3schools.com

W3Schools 經過最佳化,旨在方便學習和培訓。示例可能經過簡化,以提高閱讀和學習體驗。教程、參考資料和示例會不斷審查,以避免錯誤,但我們無法保證所有內容的完全正確性。使用 W3Schools 即表示您已閱讀並接受我們的使用條款Cookie 和隱私政策

版權所有 1999-2024 Refsnes Data。保留所有權利。W3Schools 由 W3.CSS 提供支援