【C語言】動態記憶體分配小結
為什麼存在動態記憶體分配?
我們已經掌握的記憶體開闢方式有:
int val = 20;//在棧空間上開闢四個位元組
char arr[10];//在棧空間上開闢10個位元組的連續空間
但是上面開闢空間的方式有兩個特點:
1.空間開闢的大小是固定的 2.陣列在申明的時候,必須指定陣列的長度,它所需要的記憶體在編譯時分配
但是對於空間的需求,不僅僅是上面的情況,有時候我們需要的空間大小在程式執行的時候才能知道,那陣列的編譯時開闢空間的方式就不能滿足了
動態記憶體分配的介紹:
C語言提供了一個動態開闢的函式:
void malloc(size_t size);
這個函式向記憶體申請一塊連續可用的空間,並返回指向這塊空間的指標。
- 如果開闢成功,則返回一個指向開闢好空間的指標。
- 如果開闢失敗,則返回一個NULL指標,因此malloc的返回值一定要做檢查。
- 返回值的型別是void*, 所以malloc函式並不知道開闢空間的型別,具體在使用的時候使用者自己來決定。
- 如果引數size為0,malloc的行為是 標準是未定義的,取決於編譯器。
- C語言提供了另外一個函式free, 專門是用來做動態記憶體的釋放和回收的
函式原型如下:
void free(void* ptr);
free函式用來釋放動態開闢的記憶體。
- 如果引數ptr指向的空間不是動態幵闢的, 那free函式的行內是未定乂的。
- 如果引數ptr是NULL指標, 則函式什麼事都不做。
malloc
malloc和free都宣告在stdlib.h標頭檔案中。
例子:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> int main() { int *p = (int*)malloc(10 * sizeof(int)); int i = 0; if (p == NULL) { printf("%s\n", strerror(errno)); return 0; } //開闢成功 for (i = 0; i < 10; i++) { *(p + i) = 10 - i; } for (i = 0; i < 10; i++) { printf("%d\n", *(p + i)); } free(p); p = NULL; system("pause"); return 0; }
calloc
C語言還提供了一個函式叫做calloc,calloc函式也用來動態記憶體分配,原型如下:
void* calloc(size_t num, size_t size);
函式的功能是為num個大小為size 的元素開闢一塊空間, 並且把空間的每個位元組初始化為0
與函式malloc的區別只在於calloc會在返回地址之前把申請的空間的每個位元組初始化為全0。
舉個例子 :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
int *p = (int*)calloc(10, sizeof(int));
int i = 0;
if (p == NULL)
{
printf("%s\n", strerror(errno));
return 0;
}
//開闢成功
for (i = 0; i < 10; i++)
{
printf("%d\n", *(p + i));
}
free(p);
p = NULL;
system("pause");
return 0;
}
所以如果我們對申請的記憶體空間的內容要求初始化,那麼可以很方便的使用calloc函式來完成任務。
realloc
realloc函式的出現讓動態記憶體管理更加靈活。
有時候我們發現過去申請的空間太小了,有時候我們又會覺得申請的空間過大了,那為了合理的時候記憶體, 我們一定會對記憶體的大小做靈活的調整。那realloc函式就可以做到對動態開闢記憶體大小的調整。
函式原型如下 :
void realloc(void* ptr, size_t size);
ptr是要調整的記憶體地址 size 調整之後新大小 返回值為調整之後的記憶體起始位置。 這個函式調整原記憶體空間大小的基礎上,還會將原來記憶體中的資料移動到新的空間。 realloc在調整記憶體空間的是存在兩種情況 : 情況1 : 原有空間之後有足夠大的空間 情況2 : 原有空間之後沒有足夠大的空間
情況1: 當是情況1的時候,要擴充套件記憶體就直接原有記憶體之後直接追加空間,原來空間的資料不發生變化。 情況2: 當是情況2的時候,原有空間之後沒有足夠多的空間時,擴充套件的方法是 : 在堆空間上另找一個合適大小的連續空間來使用。這樣函式返回的是一個新的記憶體地址。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
int *p = malloc(10 * sizeof(int));
int i = 0;
int *ptr = NULL;
if (p == NULL)
{
return 0;
}
for (i = 0; i < 10; i++)
{
p[i] = i;
}
ptr = realloc(p, 20 * sizeof(int));
if (ptr != NULL)
{
p = ptr;
}
for (i = 0; i < 20; i++)
{
printf("%d\n", p[i]);
}
free(p);
p = NULL;
system("pause");
return 0;
}