選單
×
   ❮   
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 語言有兩種記憶體型別:靜態記憶體和動態記憶體。


靜態記憶體

靜態記憶體是在程式執行**前**為變數保留的記憶體。靜態記憶體分配也稱為*編譯時*記憶體分配。

當程式編譯時,C 語言會自動為每個變數分配記憶體。

例如,如果您建立一個包含 20 名學生(例如用於暑期學期)的整數陣列,C 語言將為 20 個元素保留空間,通常是 80 位元組的記憶體(20 * 4)。

示例

int students[20];
printf("%lu", sizeof(students)); // 80 位元組
自己動手試一試 »

但是當學期開始時,發現只有 12 名學生入學。那麼您就浪費了 8 個未使用元素的空間。

由於您無法更改陣列的大小,因此您將留下不必要的保留記憶體。

請注意,程式仍將執行,並且不會以任何方式損壞。但是,如果您的程式包含大量此類程式碼,它可能比最佳狀態執行得慢。

如果您希望更好地控制已分配的記憶體,請檢視下面的動態記憶體。


動態記憶體

動態記憶體是在程式開始執行**後**分配的記憶體。動態記憶體分配也可以稱為*執行時*記憶體分配。

與靜態記憶體不同,您可以完全控制在任何時候使用了多少記憶體。您可以編寫程式碼來確定您需要多少記憶體並進行分配。

動態記憶體不屬於變數,它只能透過指標訪問。

要分配動態記憶體,可以使用 malloc()calloc() 函式。必須包含 <stdlib.h> 標頭檔案才能使用它們。malloc()calloc() 函式分配一些記憶體並返回其地址的指標。

int *ptr1 = malloc(size);
int *ptr2 = calloc(amount, size);

malloc() 函式有一個引數,size,它指定要分配的記憶體量,以位元組為單位。

calloc() 函式有兩個引數

  • amount - 指定要分配的專案數量
  • size - 指定每個專案的大小,以位元組為單位

注意:malloc() 分配的記憶體中的資料是不可預測的。為避免意外值,請務必在讀取記憶體之前寫入一些內容。

malloc() 不同,calloc() 函式將零寫入所有已分配的記憶體。然而,這使得 calloc() 的效率略低。

為資料型別分配正確記憶體量的最佳方法是使用 sizeof 運算子

int *ptr1, *ptr2;
ptr1 = malloc(sizeof(*ptr1));
ptr2 = calloc(1, sizeof(*ptr2));

小心 sizeof(*ptr1) 告訴 C 語言測量地址處資料的大小。如果您忘記 * 而改為寫入 sizeof(ptr1),它將測量指標本身的大小,這通常是儲存記憶體地址所需的 8 個位元組。

注意:sizeof 運算子無法測量分配了多少動態記憶體。測量動態記憶體時,它只告訴您記憶體*資料型別*的大小。例如,如果您為 5 個 float 值保留空間,sizeof 運算子將返回 4,這是一個 float 值所需的位元組數。

讓我們使用動態記憶體來改進上面的學生示例。

如前所述,我們不能使用 sizeof 來測量分配了多少記憶體,我們必須透過將專案數量乘以資料型別的大小來計算。

示例

int *students;
int numStudents = 12;
students = calloc(numStudents, sizeof(*students));
printf("%d", numStudents * sizeof(*students)); // 48 位元組
自己動手試一試 »

注意

在使用動態記憶體分配時,您還應該**檢查錯誤**並在程式結束時**釋放記憶體**。您將在下一章中瞭解更多資訊。


棧記憶體

為了完整起見,值得一提的是棧記憶體。棧記憶體是一種動態記憶體,它為函式內部宣告的變數保留。在函式內部宣告的變數使用棧記憶體而不是靜態記憶體。

當函式被呼叫時,會為函式中的變數分配棧記憶體。當函式返回時,棧記憶體被釋放。

瞭解棧記憶體對於處理巢狀函式呼叫和遞迴的記憶體使用很有幫助。重複次數過多的遞迴可能會佔用過多的棧記憶體。當這種情況發生時,稱為**棧溢位**。



×

聯絡銷售

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

報告錯誤

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

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

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