了解動態內存函數
- 前言:
- 一、malloc函數
- 二、calloc函數
- 三、realloc函數
- 四、free函數
前言:
在C語言中,動態內存函數是塊重要的知識點。以往,我們開辟空間都是固定得,數組編譯結束后就不能繼續給它開辟空間了,開辟的空間滿了,就不能在開辟空間了(就是不能在添加數據了)。學習本文章,我們就可以解決這個問題,向內存申請空間,滿啦可以繼續申請空間。
一、malloc函數
需要頭文件——<stdlib.h>
瀏覽器直接翻譯:
malloc函數(動態內存開辟的函數):
void* malloc(size_t size);
功能:
這個函數向內存申請一個連續可用的空間,并返回指向這塊空間的指針。
- 如果開辟成功,則返回一個指向開辟好空間的指針。
- 如果開辟失敗,則返回一個NULL指針,因此malloc的返回值一定要做檢查。
- 返回值的類型是void* ,所以malloc函數并不知道開辟空間的類型,具體在使用的時候由使用者自己決定。
- 如果size為0,malloc的行為是標準還是未定義的,由編譯器決定。
- malloc申請的空間,當程序退出時,要還給操作系統,當程序不退出,動態申請的內存,不會主動釋放,需要用free函數來釋放。
malloc申請的內存空間:
malloc申請到空間后,直接返回這個空間的首地址,不會初始化空間的內容。
舉個例子:
#include <stdio.h>
#include <stdlib.h>
int main()
{
//變長數組的知識點(vs不能用,gcc可以用)//int num = 0;//scanf("%d", &num);//int arr[num] = { 0 };int* ptr = NULL;ptr = (int*)malloc(40);if (ptr == NULL)//判斷ptr指針是否為空{perror("malloc");exit; }else{int i = 0;for (i = 0; i < 10; i++)//給開辟的空間賦值ptr[i] = i + 1;}free(ptr);//釋放ptr指向的空間ptr = NULL;//讓ptr指向空return 0;
}
二、calloc函數
需要頭文件——<stdlib.h>
瀏覽器直接翻譯:
calloc函數(動態內存分配函數):
void* calloc(size_t num, size_t size);
功能:
- 函數的功能是,為num個大小為size元素開辟一塊空間,并且把空間的每一個字節初始化為0.
- 與malloc函數的區別,只在于calloc函數會在返回地址之前把申請空間的每一個字節初始化為0.
舉個例子:
#include <stdio.h>
#include <stdlib.h>
int main()
{int* p = (int*)calloc( 10,sizeof(int));if (p == NULL)//成立,開辟失敗{perror("calloc");exit;}free(p);p = NULL;return 0;
}
p指向的地址:
三、realloc函數
需要頭文件——<stdlib.h>
瀏覽器直接翻譯:
realloc函數(動態內存管理更加靈活):
有時候我們發現過去申請的空間小了,有時候我們會覺得過去申請的空間過大,為了合理使用內存,我們一定要對內存的大小做靈活的調整。realloc函數可以做到對動態開辟內存大小進行調整。
void* realloc(void* ptr, size_t size);
功能:
- ptr是要調整的內存地址。
- size是調整后的新大小。
- 返回值為調整之后的內存起始位置。
- 這個函數在調整原空間大小的基礎上,還會將原來的數據移到新的空間。
注意:
realloc調整內存空間有兩種情況。-
情況1:原有空間之后有足夠大的空間(原地擴容)。
當是情況1的時候,要擴展內存就直接在原有內存之后直接追加空間,原來空間的數據不發生改變。
-
情況2:原有空間后面沒有足夠大的空間(異地擴容)。
當是情況2的時候,原有空間后面沒有足夠多的空間時,擴展的方法是:在堆空間上另外找一個合適大小的連續空間來使用。這樣函數返回的是一個新的內存地址。
所以我們在使用realloc函數的時候一定要注意:
1、開辟新的空間。
2、 會將舊的空間數據拷貝到新的空間。
3、釋放舊的空間。
4、返回新空間的起始地址。
舉個例子:
-
#include <stdio.h>
#include <stdlib.h>
int main()
{int* ptr =(int*) malloc( 100 );if (ptr != NULL){
//可以使用這個空間}else{perror("malloc");exit;}//擴展空間int* p = (int*)realloc(ptr, 1000);//可能增容失敗if (p != NULL){//增容成功ptr = p;//p指向的空間交給ptr去維護}free(ptr);//把開辟早堆上的空間釋放掉ptr = NULL;return 0;
}
四、free函數
需要頭文件——<stdlib.h>
瀏覽器直接翻譯:
free函數(釋放動態開辟的內存):
void* free(void* ptr);
功能:
- 如果參數ptr指向的那個空間不是動態開辟的,那free函數的行為是未定義的。
- 如果參數ptr是NULL指針,則函數什么事都不做。