C語言 動態內存分配

動態內存分配

在這裏插入圖片描述
#千鋒教育 物聯網逆戰班#
天才就是無止境刻苦勤奮的能力。

1、malloc函數 和 free函數

1.1、malloc函數

#include<stdlib.h>
void *malloc(unsigned int num_size);
形參:num_size需要申請空間大小的字節數。
返回值:
    成功:返回空間的起始地址
    失敗:NULL
特點:
    1、對於malloc的返回值 一般要強制類型轉換
    2、malloc申請的空間 內容不確定  一般使用memset進行清空
   3、多次調用malloc 第1次malloc 和 第2次malloc的地址不一定連續 

1.2、free函數

void free(void *addr);
釋放堆區空間

1.3、案例1:從堆區申請 一個int空間

void test02()
{
	int *addr = NULL;

	addr = (int *)malloc(sizeof(int));
	if(addr == NULL)//申請失敗了
	{
		printf("malloc err\n");
		return;
	}

	printf("*addr=%d\n", *addr);//不確定的值
	
	//對堆區空間 清0
	memset(addr, 0, sizeof(int));
	printf("*addr=%d\n", *addr);//0

	//對addr的空間 就行寫 或 讀
	*addr = 1000;//寫

	printf("*addr=%d\n", *addr);//1000 讀


	//釋放堆區空間 空間使用權限的回收 是否對空間內容清0 這是不確定的
	free(addr);
}
int main(int argc,char *argv[])
{
	test02();
	return 0;
}

運行結果:
在這裏插入圖片描述

1.4、案例2:從堆區申請一個數組 數組的大小 由用戶決定

int get_n(void)
{
	int n = 0;
	printf("請輸入元素的個數:");
	scanf("%d", &n);
	return n;
}
int* get_addr(int n)
{
	return (int *)malloc(n*sizeof(int));
}
void my_input_array(int *arr, int n)
{
	int i=0;
	//記得將arr指向的空間清0
	memset(arr,0,n*sizeof(int));

	//獲取鍵盤輸入
	printf("請輸入%d個int數據\n",n);

	for(i=0;i<n; i++)
	{
		scanf("%d", arr+i);
	}
}
void my_print_array(int *arr, int n)
{
	int i=0;
	for(i=0;i<n;i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
void test04()
{
	int *arr=NULL;
	int n = 0;
	//得到用戶輸入的元素個數
	//1、獲取用戶大小
	n = get_n();
	//定義函數 給arr申請堆區空間
	arr = get_addr(n);
	if(arr == NULL)
	{
		perror("get_addr");
		return;
	}
	//對空間讀寫操作
	my_input_array(arr, n);
	//對空間數組遍歷
	my_print_array(arr, n);
	//釋放空間
	free(arr);
}
int main(int argc,char *argv[])
{
	test04();
	return 0;
}

運行結果:
在這裏插入圖片描述

2、calloc函數

#include<stdlib.h>
void * calloc(size_t  nmemb,size_t  size);
參數:
    1、nmemb 申請的數據塊數
    2、size  每一塊大小
    3、所以申請總大小=nmemb * size  
返回值:
    成功:返回空間的起始地址
    失敗:返回NULL
特點:申請的空間自動清零    

案例:

void test04()
{
	int n = 0;
	int i=0;
	int *arr=NULL;

	//1、獲取用戶大小
	printf("請輸入元素的個數:");
	scanf("%d", &n);
	//2、根據大小從堆區申請空間
#if 0
	arr = (int *)malloc(n*sizeof(int));
	if(NULL == arr)
	{
		//perror 錯誤輸出
		perror("mallac");
		return;
	}
	memset(arr,0,n*sizeof(int));//清零
#endif

#if 1
	arr=(int *)calloc(n, sizeof(int));//自動清零  不需要使用memset
	if(NULL == arr)
	{
		//perror 錯誤輸出
		perror("calloc");
		return;
	}
#endif
	//對arr的讀寫操作
	printf("請輸入%d個int數據\n",n);
	for(i=0;i<n; i++)
	{
		scanf("%d", arr+i);
	}
	//遍歷數組
	for(i=0;i<n;i++)
	{
		printf("%d ", arr[i]);
	}
	//釋放空間
	free(arr);

}

3、realloc動態追加或減少空間

#include<stdlib.h>
void* realloc(void *s, unsigned int newsize);

功能:

在原先s指向的內存基礎上重新申請內存,新的內存的大小爲 new_size 個 字節,如果原先內存後面有足夠大的空間,就追加,
如果後邊的內存不	夠用,則realloc函數會在堆區找一個newsize個字節大小的內存申請,
將原先內存中的內容拷貝過來,然後釋放原先的內存,最後返回新內存的地址。
參數:s:原先開闢內存的首地址    newsize:新申請的空間的大小
返回值:新申請的內存的首地址 
注意:一定要保存 realloc的返回值

案例

void test06()
{
	int *arr = NULL;
	int n = 0;
	int i=0;
	int n_new = 0;

	//1、獲取用戶大小
	printf("請輸入元素的個數:");
	scanf("%d", &n);
	
	arr=(int *)calloc(n, sizeof(int));//自動清零  不需要使用memset
	if(NULL == arr)
	{
		//perror 錯誤輸出
		perror("calloc");
		return;
	}

	printf("請輸入%d個int數據\n",n);
	for(i=0;i<n; i++)
	{
		scanf("%d", arr+i);
	}

	//遍歷數組
	for(i=0;i<n;i++)
	{
		printf("%d ", arr[i]);
	}

	//再追加5個元素
	printf("請輸入新增的元素個數:");
	scanf("%d", &n_new);
	arr = (int *)realloc(arr, (n+n_new)*sizeof(int));

	printf("請輸入新增的%d個int數據\n",n_new);
	for(i=n;i<(n+n_new); i++)
	{
		scanf("%d",arr+i);
	}

	for(i=0;i<(n+n_new);i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	free(arr);
}
int main(int argc,char *argv[])
{
	test06();
	return 0;
}

運行結果:
在這裏插入圖片描述

4、堆區空間使用的注意事項

void test08()
{
	int *p2 = NULL;
	int *p3 = NULL;
	//1、指向堆區空間的指針變量 不要隨意的更改指向
	int *p=(int *)calloc(1,sizeof(int));
	int num = 10;
	p = #//p指向num  導致calloc申請的空間泄露

	//2、不要操作已經釋放的空間
	p2 = (int *)calloc(1,sizeof(int));
	*p2 = 1000;
	//釋放該空間
	free(p2);
	printf("*p2 = %d\n", *p2);//不確定

	//3、不要對堆區空間重複釋放
	p3 = (int *)calloc(1,sizeof(int));
	free(p3);
	free(p3);// err 多次釋放
}

5、防止多次釋放

void test09()
{
	int *p = (int *)calloc(1,sizeof(int));

	if(p != NULL)//防止多次釋放
	{
		free(p);
		p=NULL;
	}
	if(p != NULL)
	{
		free(p);
		p=NULL;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章