C:动态内存分配(1)

函数介绍:

  • 栈:在函数内部声明的所有变量都将占用栈内存。用于存放局部变量、函数的形参;
  • 堆:这是程序中未使用的内存,在程序运行时可用于动态分配内存。用于动态内存分配;
  • 静态区:用于存放全局变量、静态变量(例如static int)。

局部变量和局部数组在栈区开辟空间;

全局变量和全局数组在静态区开辟空间;

本部分主要包括malloc、free、calloc和realloc四个函数的应用:

struct S
{
	char name[20];
	int age;
};
int main()
{
    //数组的变量必须是常量,不是所有编译器都支持变长数组
	struct S arr[50];//创建一个结构体数组,存放多个人的信息,相当于通讯录中的data[MAX]
	//30,浪费了空间;60,不够
	//malloc/free/calloc/relloc

	//malloc开辟空间


	return 0;
}

一、malloc函数

此函数用于向内存申请空间

函数格式如下:

void* malloc (size_t size);

即向内存申请(size_t size) 个字节的内存空间;

下面代码表示向内存申请10个整形的空间:

	//向内存申请10个整形的空间
	int* p=(int*)malloc(10 * sizeof(int));

malloc函数的应用如下:

1.定义整形指针p用于接收malloc函数开辟的空间的地址;

2.判断malloc函数是否开辟空间成功,如果p为空指针,则开辟空间失败;

3.进行for循环,将i的值依次赋给p+i;

4.进行打印*(p+i)的结果;

注意:需要free函数释放空间,可以理解为使用完的空间要还回去,free函数与malloc函数成对配合使用。

int main()
{
	//向内存申请10个整形的空间
	int* p=(int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));//打印错误原因的一个方式
	}
	else
	{
		//正常使用空间
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			*(p + i) = i;
		}
		for (i = 0; i < 10; i++)
		{
			printf("%d ", *(p + i));
		}
	}
	//当动态申请的空间不再使用的时候
	//就应该还给操作系统
	free(p);//释放空间

	//malloc和free成对使用
	return 0;
}

输出结果为0 1 2 3 4 5 6 7 8 9 

二、calloc函数

calloc函数也用来动态内存分配,开辟需要的空间,并把每个字节都初始化为0。

函数格式如下:

void* calloc (size_t num, size_t size)

 num为要分配的元素数量;size为要分配的类型的大小;

下面代码为向内存申请10个 sizeof(int)= 4 大小的字节。

int* p= (int*)calloc(10, sizeof(int));

 calloc函数的应用如下:

1.定义整形指针指向calloc函数开辟的空间地址;

2.判断calloc是否开辟成功,若p为空指针,则错误;

3.下面代码同malloc函数的应用。

int main()
{
	//malloc(10*sizeof(int))
	int* p= (int*)calloc(10, sizeof(int));
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
	}
 else
	{
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			printf("%d ", *(p + i));
		}
	}
	//释放空间
	//free函数是用来释放动态开辟的空间的
	free(p);
	p = NULL;
	return 0;
}

三、realloc函数

用于调整动态内存开辟的空间

函数格式如下:

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

ptr为要调整的内存地址;size为调整目标大小; 

下面代码的作用是调整p的动态内存空间大小为40个字节;

int* p2=realloc(p, 40);

realloc函数的应用如下:

1.定义整形指针指向malloc函数开辟的空间地址;

2.判断malloc是否开辟成功,若p为空指针,则错误;

3.为*(p+i)赋值;

4.通过realloc函数调整p地址指向的内存空间调整为40个字节的大小;

5.判断realloc函数是否修改空间成功,如果p为空指针,则内存空间开辟失败;

6.进行for循环,将i的值依次赋给p+i;

7.进行打印*(p+i)的结果;

int main()
{
	int* p = (int*)malloc(20);
	if (p == NULL)//开辟空间失败
	{
		printf("%s\n", strerror(errno));
	}
	else
	{
		int i = 0;
		for (i = 0; i < 5; i++)
		{
			*(p + i) = i;
		}
		//就是在使用malloc开辟的20个字节的空间
		//假设这里20个字节不能满足我们的使用
		//希望能有40个字节的空间
		//这里就可以使用realloc来调整动态开辟的内存
		// 
		int* p2=realloc(p, 40); 
		// 
		//realloc使用注意事项
		//1.如果p指向的空间之后有足够的内存空间可以追加,则直接追加,后返回p
		//2.如果p指向的空间之后没有足够的内存空间可以追加,则realloc函数会重新找一块新的内存区域开辟新的一块满足需求的空间,并且把原来内存中的数据copy回来,释放旧的内存空间,最后返回新开辟的空间地址
		//3.要用一个新的变量来接受mealloc函数的返回值
		//
		//int* ptr = realloc(p.INT_MAX);
		if(ptr != NULL)
		{
			p = ptr;
			int i = 0;
			for (i = 5; i < 10; i++)
			{
				*(p2 + i) = i;
			}

			for (i = 0; i < 10; i++)
			{
				printf("%d ", *(p2 + i));
			}
		}

	}
	//释放内存
	free(ptr)
	return 0;
}

另外,realloc指针参数如果为空指针NULL,则相当于malloc(40)。 


int* p3 = realloc(NULL, 40);//相当于malloc(40)

常见错误:

1、对空指针进行解引用

malloc函数可能开辟空间失败。

int* p = (int*)malloc(40);
	//万一malloc失败,p被赋值为NULL,for里非法--空指针解引用
	*p = 0;//err
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	free(p);
	p = NULL;

2、对开辟的动态内存进行越界访问

动态内存开辟的大小为5个整形,而for循环中循环执行了10个整形,越界访问。

int* p = (int*)malloc(5 * sizeof(int));
	if (p == NULL)
	{
		return 0;
	}
	else
	{
		int i = 0;
		for (i = 0; i < 10; i++) //malloc中只有5个整形的空间,此处10,形成越界访问
		{
			*(p + i)=i;
		}
	}
	free(p);
	p = NULL;

3、对非动态开辟内存的free

指针p指向的内存不是动态内存,无需释放。

int a = 10;
	int* p = &a;
	*p = 20;
	free(p);//对非动态开辟内存的free
	p = NULL;

4、使用free释放动态内存开辟内存的一部分(p指向的地址变化了);

*p++ = i;

此代码改变了指针p的位置,当释放时,从p之后开始释放,p前的内存没有释放。 

int* p = (int*)malloc(40);
	if (p == NULL)
	{
		return 0;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*p++ = i;//释放空间要从p往后,但p变化了,并不是起始位置
	}
	//回收空间
	//使用free释放动态开辟内存的一部分
	free(p);

5、对同一块动态开辟的内存空间进行多次释放;

多次free(p);在第一次free之后添加

p = NULL;

 下面再出现free()代码,就不会出现重复释放问题。

int* p = (int*)malloc(40);
	if (p = NULL)
	{
		return 0;
	}
	//使用空间
	//释放空间
	free(p);
	//p = NULL;//此行代码之后后面再释放空指针不会有问题
	//....
	//重复释放空间
	free(p);
//谁申请谁回收

6、对动态开辟内存忘记释放(内存泄漏)

没有free()函数。

while (1)
	{
		malloc(1);
		sleep(1000);
	}


	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值