初识C语言:5. 动态内存管理

1. 动态内存的重要性

有些时候,我们需要的空间大小只有在程序运行的时候才能知道,而普通的数组开辟的空间是指定长度的,固定不变的,这就带来了不便。


2.动态内存函数的

2.1 malloc

void* malloc(size_t size);
  • malloc可以向内存申请一块连续的内存,并且返回指向这块空间的指针。
  • 如果开辟空间失败,malloc会返回一个NULL指针,因此对于malloc的返回值一定要记得检查。
  • 由于系统不知道使用者对于申请空间的用处,所以返回的是一个void*类型的指针,让使用者在使用时自己去强制转换
    malloc的参数代表开辟多大的字节,如果为0,结果不定,取决于编译器

2.2 free

void* free(void* ptr);
  • C语言中所有动态开辟的空间都需要释放和回收,而free函数就是专门做这个工作的。
  • 如果free释放的空间不是动态开辟的,那么结果是未知的
  • 如果参数ptr为NULL,那么free函数什么都不做
  • 释放内存过后要将ptr=NULL;

2.3 calloc

void* calloc(size_t num,size_t size);

calloc函数和malloc的功能大同小异,都是开辟一块指定大小的内存空间,不同的是

  1. calloc开辟的空间会将每个字节都初始化为0
  2. calloc所需参数与malloc不同,calloc会开辟num个size大小的空间,也就是说,calloc开辟的空间大小是num*size

2.4 realloc

void* realloc(void* ptr,size_t size)
  • realloc函数是让内存动起来的关键,使用它可以根据需要来动态地调整动态空间的大小。
  • realloc会把ptr指向的空间大小修改为size大小,并返回指向更新后空间地址的指针
  • realloc的使用会有两种情况:
  1. 原有空间的后面有足够大的空间,那么扩容时就单纯的追加空间即可
  2. 原有空间的后面没有足够大的空间,那么扩容时就要找到一块新的空间来开辟,将之前空间里的数据复制过来,这块新的空间直接就是size大小,因此realloc函数有时会返回一个新的地址

3. 动态内存使用时的一些典型错误

3.1 对NULL指针解引用

void test()
{
	int* p=(int*)malloc(10);
	*p=20;
	free(p);
}

这个代码的问题在于,如果malloc开辟空间失败,那么*p=20就是对NULL指针解引用,是错误的


3.2 用free释放非动态空间

void test()
{
	int a=10;
	int* p=&a;
	free(p);
}

3.3 用free释放动态空间的一部分

void test()
{
	int* p=(int*)malloc(100);
	p++;
	free(p);
}

p已经不指向这块内存的起始位置,所以不能将p传给free来释放


3.4 用free多次释放动态空间

void test()
{
	int* p=(int*)malloc(100);
	free(p);
	free(p);
}

p第一次释放过后还没有置空,不能再释放第二次


3.5 未释放动态内存

void test()
{
	int* p=(int*)malloc(100);
}

忘记释放的动态内存会造成内存泄漏


4.动态内存笔试题

4.1

void Getmemory(char* p)
{
	p=(char*)malloc(100);
}
void test()
{
	char* str=NULL;
	GetMemory(str);
	strcpy(str,"hello world");
	printf(str);
}

这个程序会打印出hello world吗?

是不行的

因为GetMemory(char* p)是接收一个指针变量,并将一块空间的地址赋给这个指针,但是在函数中,这个指针p只是str这个实参的一个临时复制,它出了GetMemory这个函数就会销毁,所以malloc开辟的这块空间就没有指针指向他了,str还是一个NULL指针


4.2 返回栈空间地址问题

void Getmemory(char* p)
{
	char p[]="hello world";
	return p;
}
void test()
{
	char* str=NULL;
	str=GetMemory();
	printf(str);
}

这个程序会打印出hello world吗?

同样是不行的

出了这个函数,p指向的空间被系统收回,str称为野指针


5.柔性数组

5.1定义

C99中,结构体中最后一个元素允许是未知大小的数组,这就叫做柔性数组

struct s
{
	int i;
	int a[0];//这就是柔性数组成员
};
struct s
{
	int i;
	int a[];//这也是柔性数组成员
};

5.2 特点

  • 柔性数组成员前必须有至少一个其他成员
  • sizeof计算的结构体大小不包括柔性数组成员的内存大小
  • 含有柔性数组的结构体应用malloc()函数进行内存分配
typedef struct S
{
	int i;
	int a[];
}S;

S* p=malloc(sizeof(S)+10*sizeof(int));
p->i=100;
for(i=0;i<100;i++)
{
	p->a[i]=i;
}

free(p);

相当于获得了100个整型元素的连续空间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值