C语言动态内存开辟

Posted Ja_King_ZH

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言动态内存开辟相关的知识,希望对你有一定的参考价值。

动态内存开辟

1.malloc、free

1.1 malloc的原型为:

void *malloc( size_t size );

1.2 malloc的用法:

看下面代码:

int* p=(int*)malloc(10*sizeof(int));

上面代码意思是开辟10个int类型大小的空间,将其强制转换为int型,并用int类型指针接收。
1.若开辟成功,则返回开辟空间的头指针。
2.若开辟失败,则返回空指针。
所以,用了malloc后一定要判断!
如下面代码:

#include<stdio.h>
#include<stdlib.h>// malloc 所在头文件
#include<errno.h>// errno,h 错误码库
int main()       // 与 函数 strerror(错误信息报告)  搭配使用,将错误码转化为错误信息,并返回它的地址

	// 我想向内存申请 10个 整形的 空间
	int* p = (int*)malloc(/*INT_MAX*/10 * (sizeof(int)));// 因为  malloc 函数 返回的是 万能*(无类型)指针,所以需要转化类型
	// malloc 函数 也有 开辟空间失败的时候,
	// 比如 内存 只有 4 个 g ,我要开辟 8 g 空间,这肯定是会失败的,返回 空指针 NULL
	
	if (p == NULL)
	
		// 找出打印错误原因的方式
		printf("%s\\n", strerror(errno));// malloc(INT_MAX)
		                //输出 Not enough space
	
	else
	
		// 正常使用 空间
		int i = 0;
		for (i = 0; i < 10; i++)
		
			*(p + i) = i;// 赋值 0 1 2 3 4 5 6 7 8 9
		
		for (i = 0; i < 10; i++)
		
			printf("%d ", *(p + i));// 输出 0 1 2 3 4 5 6 7 8 9
		
		printf("\\n");
	
	// 当动态申请的空间 不再使用的时候
	// 就会把空间 还给 操作系统
	// 这时候 就会用到 free 函数
	return 0;

而malloc的使用需和free一起,即:用malloc开辟一处空间,必须由free来释放。否则会造成内存泄露!

1.3 free的原型:

void free( void *memblock );

1.4 free的用法:

free专门用于动态内存的释放和回收。如下代码:

#include<stdio.h>
#include<stdlib.h>// malloc,free 所在头文件
#include<errno.h>
int main()

	// 我想向内存申请 10个 整形的 空间
	int* p = (int*)malloc(10 * (sizeof(int)));
	if (p == NULL)
	
		// 找出打印错误原因的方式
		printf("%s\\n", strerror(errno));// malloc(INT_MAX)
		                //输出 Not enough space
	
	else
	
		// 正常使用 空间
		int i = 0;
		for (i = 0; i < 10; i++)
		
			*(p + i) = i;// 0 1 2 3 4 5 6 7 8 9
		
		for (i = 0; i < 10; i++)
		
			printf("%d ", *(p + i));// 0 1 2 3 4 5 6 7 8 9
		
		printf("\\n");
	
	// 当动态申请的空间 不再使用的时候
	// 就会把空间 还给 操作系统
	// 这时候 就会用到 free 函数
	free(p);// 用完了再释放,也就是说 在打印完之后(调用完之后),再释放(p的值没有改变,还可以通过它找到该空间)
	//  虽然当前空间 不属于当前程序,但是依然 可以通过 p  找到  该空间,很有可能会破坏这个空间
	//  所以先在这个 指针 依然很危险

	p = NULL; // free函数 释放完空间后,不会改 p 的值,所以我们自己主动改
	return 0;

// 最后请注意:free 是用来 释放 动态开辟的内存

// free 函数 的 特殊情况:
//1. 如果参数 ptr 指向的空间不是动态开辟的,那 free 函数的行为是未定义的
//2. 如果参数 ptr 是 NULL 指针,则函数 什么 都不做。

1.首先,将动态开辟的空间free掉。
2.再将free掉的空间的头指针制为空即可。

2.calloc

2.1 calloc原型:

void *calloc( size_t num, size_t size );

2.2 calloc用法:

calloc和malloc一样,都用于动态内存开辟,区别点在于calloc具有初始化功能,即:calloc可将开辟的空间进行初始化操作。
如下代码:

 用法跟 malloc 函数差不多
#include<stdio.h>
#include<errno.h>
#include<string.h>
int main()
                     // 开一块空间,空间大小为 10 * int == 40 字节
	int* p = (int*)calloc(10, sizeof(int));// 比 malloc 函数 多一个元素个数 参数
	if (p == NULL)    
	
		printf("%s\\n", strerror(errno));
	
	else
	
		int i = 0;
		for (i = 0; i < 10; i++)// 因为 p 为整形指针变量,指向一个 int 类型 元素,所以有 10个 int 元素
		
			printf("%d ", *(p + i));// 0 0 0 0 0 0 0 0 0 0
		  //calloc 在开辟好空间后,会把空间的所有字节内容全部初始化为 零
	
	free(p);
	p = NULL;// 狗头拿来!!
	return 0;

3.realloc

3.1 realloc原型:

void *realloc( void *memblock, size_t size );

3.2 realloc用法:

有时我们会发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,为了合理的使用内存,我们一定会对内存的大小做灵活的调整,realloc函数就可以做到对动态开辟内存大小的调整。
如以下代码:

#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, char* argv[], char* envp[])

	int input;
	int n;
	int *numbers1;
	int *numbers2;
	numbers1=NULL;
 
	if((numbers2=(int *)malloc(5*sizeof(int)))==NULL)//为numbers2在堆中分配内存空间
	
		printf("malloc memory unsuccessful");
		exit(1);
	
	
	printf("numbers2 addr: %8X\\n",(int)numbers2);
 
	for(n=0;n<5;n++) //初始化
	
		*(numbers2+n)=n;
		//printf("numbers2's data: %d\\n",*(numbers2+n));
	
 
	printf("Enter new size: ");
	scanf("%d",&input);
 
	//重新分配内存空间,如果分配成功的话,就释放numbers2指针,
	//但是并没有将numbers2指针赋为NULL,也就是说释放掉的是系统分配的堆空间,
	//和该指针没有直接的关系,现在仍然可以用numbers2来访问这部分堆空间,但是
	//现在的堆空间已经不属于该进程的了。
	numbers1=(int *)realloc(numbers2,(input+5)*sizeof(int));
 
	if(numbers1==NULL)
	
		printf("Error (re)allocating memory");
		exit(1);
	
	
	printf("numbers1 addr: %8X\\n",(int)numbers1);
 
	/*for(n=0;n<5;n++) //输出从numbers2拷贝来的数据
	
		printf("the numbers1's data copy from numbers2: %d\\n",*(numbers1+n));
	*/
 
	for(n=0;n<input;n++)//新数据初始化
	
		*(numbers1+5+n)=n+5;
		//printf("numbers1' new data: %d\\n",*(numbers1+5+n));
	
 
	printf("\\n");
 
	free(numbers1);//释放numbers1,此处不需要释放numbers1,因为在realloc()时已经释放
	numbers1=NULL;
	//free(numbers2);//不能再次释放
	return 0;

1.如果当前内存段后有足够的空间,realloc()返回原来的指针。
2.如果当前内存段后没有足够的空间,realloc()返回一个新的内存段的指针

以上是关于C语言动态内存开辟的主要内容,如果未能解决你的问题,请参考以下文章

用C语言分配开辟内存问题

C++ 动态内存开辟

C++ 动态内存开辟

C语言动态内存管理以及开辟的注意事项⚠️

C语言学习笔记(16)动态内存管理

C语言动态内存开辟