【回顾C语言】动态内存开辟

目录

一.内存空间

二.动态内存开辟

1.malloc函数

2.calloc函数

3.realloc函数

4.free函数

5.动态开辟内存易错点

(1)对空指针进行操作

(2)对动态开辟的内存的越界访问

(3)对非动态开辟内存的指针进行free

(4)使用free释放动态开辟内存的一部分

(5)对同一块动态内存的多次释放


一.内存空间

内存空间分为四部分:栈区,堆区,静态区,内核区

栈区:存储局部变量,函数的形式参数

堆区:存储动态内存分配的数据

静态区:存储全局变量,静态变量

内核区:由操作系统管理

二.动态内存开辟

C语言的动态内存开辟所需要的函数为malloc,realloc,calloc,free

所引用的头文件为stdlib.h

1.malloc函数

函数定义:void *__cdecl malloc(size_t  _Size)

表示在堆区开辟一块可用的连续的内存来存储数据,所以需要我们说明开辟的空间的大小,即malloc函数的参数size_t(表示无符号整形)

因为其返回类型为一个void*类型的指针,所以当我们用一个int或其他类型的指针来接收指向这片空间时,就需要对malloc的返回指针进行显式类型转换,即强转

eg:int* p=(int*)malloc(sizeof(int)*30)

由于需要知道具体的开辟空间大小,所以需要通过sizeof计算开辟的数据类型再*开辟个数

malloc开辟空间成功返回该空间的元素首地址,开辟失败则返回一个空指针

2.calloc函数

函数定义:void *__cdecl calloc(size_t _Count, size_t _Size)

第一个参数size_t_Count为开辟数组的元素个数

第二个参数size_t_Size为数组元素占用的字节数

eg:int* p=(int*)calloc(30,sizeof(int))

calloc和malloc函数基本一样,开辟空间的要求也只是格式不同,返回的类型也是一致

差别就是calloc开辟内存空间时会将每个字节初始化为0

3.realloc函数

函数定义: void *__cdecl realloc(void *_Block, size_t _Size) 

realloc是在已经利用malloc或calloc开辟的空间后进行调整,可拓展可缩减(缩减会造成数据丢失),若开辟的空间后面没有足够的空间继续开辟,则重新寻找一块新的空间进行新空间的开辟

所以,

第一个参数是已经开辟的空间的指针

第二个参数为新开辟空间的字节数,不是增加的字节数

eg: int* q=(int*)realloc(p,sizeof(int)*50)

表示将空间修改为50内存,并返回指向该空间第一个元素的地址,失败则返回空指针

realloc若开辟的空间不够则会将旧空间的数据复制到新空间并进行开辟

成功则会自动释放旧空间,不需要手动释放

若开辟失败则放回空指针,所以realloc维护的指针和旧空间维护的指针不能是同一个,否则一旦开辟失败该指针置为空那么旧空间的地址也将丢失

 所以需要分能否开辟成功来进行讨论

int main()
{
	int* p = malloc(sizeof(int) * 30);

	int* q = realloc(p, sizeof(int) * 50);

	if (q != NULL)//开辟成功
	{
		p=q;//自动释放旧空间,将新指针赋给旧指针,使指针指向新空间
		free(p);
		p = NULL;
		q = NULL;
	}
	else//开辟失败,q是空指针,相当于什么都没发生
	{
		free(p);
		p = NULL;
	}
	system("pause");
	return 0;
}

4.free函数

函数定义:void __cdecl free(void *_Block)

参数为要维护动态内存开辟的空间的指针,无返回值

如果不free开辟的空间,程序结束时操作系统也会回收空间,但并不及时,不释放内存空间就会造成内存的泄漏

free后指针指向的空间被释放,但指向动态内存空间的指针仍旧指向该空间,若不将指针置为空,则可能会存在别人利用该指针访问该空间的危险存在,所以free后指针必须置为空

在函数内部开辟空间后最好在函数内部释放,若指针是一个局部变量,存储在栈区中,那么指针出了函数作用域就会被销毁,所以释放不到该内存,但将指针设为静态变量(static)就可以,因为开辟的空间在堆区,不会随着函数的作用域而销毁

5.动态开辟内存易错点

(1)对空指针进行操作

这是最容易犯错的操作,当我们进行动态内存开辟后,往往会默认为开辟成功,一旦开辟失败,动态内存会返回空指针,那么我们就是在对空指针进行操作,无论是对地址的访问还是对空指针的操作都是非法操作

为了避免这种错误,要有对维护开辟的内存的指针进行选择判断的操作,即判断指针是否为空,只有不为空,即开辟成功才能进行操作

(2)对动态开辟的内存的越界访问

类似数组,即访问到了动态内存后面的空间

(3)对非动态开辟内存的指针进行free

free只对堆区空间释放,释放非堆区空间会报错

(4)使用free释放动态开辟内存的一部分

若改变指针的位置,则释放的是改变后的指针指向的后面的空间,前面的空间将丢失,造成错误

所以不能对维护空间的指针进行移动操作,若要操作只能赋值给一个副本进行移动,释放时仍旧释放原指针

(5)对同一块动态内存的多次释放

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值