
- C程式設計教程
- C - 首頁
- C語言基礎
- C - 概述
- C - 特性
- C - 歷史
- C - 環境設定
- C - 程式結構
- C - Hello World
- C - 編譯過程
- C - 註釋
- C - 詞法單元
- C - 關鍵字
- C - 識別符號
- C - 使用者輸入
- C - 基本語法
- C - 資料型別
- C - 變數
- C - 整數提升
- C - 型別轉換
- C - 型別強制轉換
- C - 布林值
- C語言中的常量和字面量
- C - 常量
- C - 字面量
- C - 轉義序列
- C - 格式說明符
- C語言中的運算子
- C - 運算子
- C - 算術運算子
- C - 關係運算符
- C - 邏輯運算子
- C - 位運算子
- C - 賦值運算子
- C - 一元運算子
- C - 自增和自減運算子
- C - 三元運算子
- C - sizeof 運算子
- C - 運算子優先順序
- C - 其他運算子
- C語言中的決策
- C - 決策
- C - if 語句
- C - if...else 語句
- C - 巢狀if語句
- C - switch 語句
- C - 巢狀switch語句
- C語言中的迴圈
- C - 迴圈
- C - while 迴圈
- C - for 迴圈
- C - do...while 迴圈
- C - 巢狀迴圈
- C - 無限迴圈
- C - break 語句
- C - continue 語句
- C - goto 語句
- C語言中的函式
- C - 函式
- C - 主函式
- C - 按值呼叫函式
- C - 按引用呼叫函式
- C - 巢狀函式
- C - 可變引數函式
- C - 使用者定義函式
- C - 回撥函式
- C - 返回語句
- C - 遞迴
- C語言中的作用域規則
- C - 作用域規則
- C - 靜態變數
- C - 全域性變數
- C語言中的陣列
- C - 陣列
- C - 陣列的特性
- C - 多維陣列
- C - 將陣列傳遞給函式
- C - 從函式返回陣列
- C - 變長陣列
- C語言中的指標
- C - 指標
- C - 指標和陣列
- C - 指標的應用
- C - 指標運算
- C - 指標陣列
- C - 指標到指標
- C - 將指標傳遞給函式
- C - 從函式返回指標
- C - 函式指標
- C - 指向陣列的指標
- C - 指向結構體的指標
- C - 指標鏈
- C - 指標與陣列
- C - 字元指標和函式
- C - 空指標
- C - void 指標
- C - 懸空指標
- C - 解引用指標
- C - 近、遠和巨型指標
- C - 指標陣列的初始化
- C - 指標與多維陣列
- C語言中的字串
- C - 字串
- C - 字串陣列
- C - 特殊字元
- C語言中的結構體和聯合體
- C - 結構體
- C - 結構體和函式
- C - 結構體陣列
- C - 自引用結構體
- C - 查詢表
- C - 點(.)運算子
- C - 列舉(或列舉型別)
- C - 結構體填充和打包
- C - 巢狀結構體
- C - 匿名結構體和聯合體
- C - 聯合體
- C - 位域
- C - typedef
- C語言中的檔案處理
- C - 輸入與輸出
- C - 檔案I/O(檔案處理)
- C預處理器
- C - 預處理器
- C - 預處理指令
- C - 預處理器運算子
- C - 宏
- C - 標頭檔案
- C語言記憶體管理
- C - 記憶體管理
- C - 記憶體地址
- C - 儲存類
- 其他主題
- C - 錯誤處理
- C - 可變引數
- C - 命令執行
- C - 數學函式
- C - static 關鍵字
- C - 隨機數生成
- C - 命令列引數
- C程式設計資源
- C - 問答
- C - 快速指南
- C - 速查表
- C - 有用資源
- C - 討論
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