1. 前言
當你開始用C語言寫程式時,最初可能會使用陣列來處理記憶體。然而,隨著程式變得更加複雜,你會希望能夠更靈活地管理記憶體。這時候,「動態記憶體配置」就派上用場了。malloc
是一個代表性的函式,它可以在程式執行期間根據需要動態分配記憶體。
舉個例子,malloc
就像「點餐後才開始製作的料理」,而事先固定的記憶體(陣列)則像「自助餐式的料理」。你可以根據需要的數量使用malloc
來「點餐」,並在使用完後「歸還盤子(使用free
釋放記憶體)」。在本文中,我們將深入探討malloc
的詳細用法。

2. malloc
是什麼?
malloc
是「memory allocation(記憶體分配)」的縮寫,是C語言中用來動態分配記憶體的函式。在程式執行期間,它會根據指定的大小分配記憶體,並回傳該區域的起始位址。這樣一來,程式在執行時可以靈活地使用記憶體,而不像固定大小的陣列那樣受限制。
在實際的程式碼中,malloc
的使用方式如下:
int *array = (int*)malloc(10 * sizeof(int));
這個範例分配了一個可以存放10個整數的陣列。這裡需要注意的是,malloc
回傳的是分配記憶體的起始位址,因此需要轉型成適當的資料型態。在這裡,我們使用(int*)
來轉型成整數指標。
3. malloc
的基本用法
接下來,我們來更詳細地了解malloc
的使用方法。它的基本語法如下:
void* malloc(size_t size);
malloc
函式接收一個參數,即要分配的記憶體大小(以位元組計算)。如果分配成功,它會回傳該記憶體區域的起始位址,回傳的型別是void*
,這是一種泛型指標,可以轉型成任何型別。例如:
int *array = (int*)malloc(10 * sizeof(int));
這裡的sizeof(int)
用來計算應該分配的記憶體大小,這樣可以確保程式在不同的環境下都能正確分配記憶體。記住,在使用完動態分配的記憶體後,一定要用free
函式釋放記憶體,否則會發生記憶體洩漏。

4. 使用free()
釋放記憶體的重要性
動態記憶體分配確實很方便,但有一點必須注意:你必須確保適時釋放已分配的記憶體。否則,記憶體洩漏會發生,導致程式佔用過多的記憶體資源。
使用malloc
分配的記憶體應該用free()
來釋放。例如:
free(array);
如果忘記釋放記憶體,這些未釋放的記憶體將一直存在於系統資源中,直到程式結束。對於長時間運行的程式,這可能會成為嚴重的問題。可以把這個過程想像成「你向餐廳借了一個盤子(malloc
),如果你不歸還(free
),餐廳的盤子遲早會用完」。
5. 檢查NULL
的重要性
當malloc
函式無法成功分配記憶體時,它會回傳NULL
。例如,當你嘗試分配的記憶體過大,導致系統無法提供足夠的記憶體時,就會發生這種情況。因此,在使用malloc
時,務必要檢查回傳值是否為NULL
,以確保記憶體分配成功。
int *array = (int*)malloc(100000000 * sizeof(int));
if (array == NULL) {
// 記憶體分配失敗時的處理
printf("記憶體分配失敗。\n");
return 1;
}
透過這種方式,我們可以在記憶體分配失敗時執行適當的錯誤處理,避免程式發生意外錯誤。加入這種安全檢查,可以有效防止記憶體相關的問題發生。

6. malloc
與calloc
的差異
在C語言中,除了malloc
,還有另一個常見的動態記憶體分配函式calloc
。這兩者的主要差異如下:
malloc
:分配記憶體時,內容是不確定的(未初始化)。calloc
:分配記憶體時,會將所有位元組初始化為零。
calloc
的使用方式
int *array = (int*)calloc(10, sizeof(int));
上面的程式碼分配了一個可以存放10個整數的陣列,並且所有的數值預設都為零。與malloc
不同,calloc
需要傳遞兩個參數:「元素個數」與「每個元素的大小」。這種方式在處理多個元素的陣列時更加直觀。
在選擇使用哪一種函式時,如果你希望分配的記憶體能夠自動初始化為零,那麼calloc
是一個不錯的選擇。否則,如果你想要更高的執行效能,並且可以手動初始化記憶體,則malloc
會更適合。
7. 實際案例:使用malloc
動態分配字串
在C語言中,通常使用固定大小的陣列來儲存字串,但如果我們需要在執行期間動態改變字串的長度,則可以使用malloc
來分配記憶體。
char *str = (char*)malloc(50 * sizeof(char));
if (str == NULL) {
printf("記憶體分配失敗。\n");
return 1;
}
sprintf(str, "Hello, World!");
printf("%s\n", str);
free(str);
這段程式碼分配了一個大小為50個字元的字串,然後將”Hello, World!”存入其中。在使用完記憶體後,記得使用free
釋放,以避免記憶體洩漏。

8. malloc
用於結構體
在C語言中,結構體是一種強大的資料型態,允許我們將多個不同型態的資料組合在一起。我們也可以使用malloc
來動態分配結構體的記憶體。
typedef struct {
int id;
char *name;
} Person;
Person *p = (Person*)malloc(sizeof(Person));
if (p == NULL) {
printf("記憶體分配失敗。\n");
return 1;
}
p->name = (char*)malloc(50 * sizeof(char));
sprintf(p->name, "John Doe");
p->id = 1;
printf("ID: %d, Name: %s\n", p->id, p->name);
free(p->name);
free(p);
在這個範例中,我們動態分配了一個Person
結構體的記憶體,並為其中的name
欄位額外分配字串記憶體。這種方法允許我們更加靈活地管理資料結構。
9. malloc
常見錯誤
- 忘記釋放記憶體:如果不使用
free()
釋放記憶體,會導致記憶體洩漏。 - 未檢查
NULL
:如果malloc
返回NULL
,應該進行錯誤處理。 - 存取未初始化的記憶體:使用
malloc
分配的記憶體預設是不初始化的,應在使用前手動初始化或使用calloc
。
10. 總結
malloc
是一個強大的工具,可讓我們在C語言中靈活地管理記憶體。透過適當的使用方式與記憶體管理技巧,可以提升程式的穩定性與效能。