这一节的内容是动态内存管理喔,指针+结构体+动态内存管理,是学习数据结构非常重要的知识,大家加油!!
点赞加关注,追番不迷路。
文章目录
1. 为什么要有动态内存分配
我们之前学习的内存开辟方式是:
int a = 10;
int arr[10] = 10;
但是这种方法有弊端:
1.空间开辟的大小是固定的
2.数组在申明的时候就必须指定它的长度,而且一旦确定不能修改
但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。
C语言引入了动态内存开辟,让程序员自己可以申请和释放空间,比较灵活,且节约空间or不浪费空间。
2. malloc和free(动态内存的申请,释放)
malloc是memory allocate:内存分配
free是自由的意思,即释放内存
malloc和free最好成对使用,有申请有释放。
2.1 malloc
malloc的基础认识
- malloc是一个申请动态内存开辟的函数。
(1)malloc的功能是allocate memory block:开辟内存块
(2)malloc的头文件是stdlib.h
(3)malloc所生成的空间是连续的
2.函数的形式是
void* malloc (size_t size)
这个函数向内存申请以块 连续 可用的空间,并返回指向这块空间的指针。
- 当需要多大的字节时,将这个数字传过去(参数是size[空间大小],参数的单位是字节)
- 这个函数返回的是void*指针,意思是当开辟了size大小的空间时,会将这个空间的起始地址传回来。如果申请失败,会返回空指针。
- malloc申请的空间和数组的空间有什么区别?
1.malloc申请的是动态内存空间,它的大小可以调节
2.开辟空间的位置不一样
malloc的应用
假设想申请10个整型的空间,如何申请?
- 1.首先:将10个整型的大小作为参数传给函数malloc
malloc(10*sizeof(int))
- 2.接下来:接收申请的空间的地址,用什么类型来接收呢?返回值的类型是 void*,用void*接收的话,之后不好使用,我们可以将地址强制类型转化成相应的,即具体在使用的时候使用者自己来决定。
int* p = (int*)malloc(10 * sizeof(int));
- 3.最后进行判断,看是否开辟成功;如果失败的话,返回原因。如果成功的话,则返回一个指向开辟好空间的指针,最后再在这10个整型的空间(40字节)存上数据。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
//接下来这一步很重要,一定要检查是否为空指针,如果是,提前返回
if (p == NULL)
{
perror("malloc");
return 1;
//在知道原因之后就退出吧,return 0是正常返回,非0是不正常返回
}
else
{
int i = 0;
for (i = 0; i < 10; i++)
*(p + i) = i;
//或者p[i]=i;
}
return 0;
}
2.2 free
1.函数free用来释放动态开辟的内存。 空间被释放之后,ptr指向的空间不属于当前程序,但是还是可以找到的(野指针)
2.函数free的原型是:void free (void* ptr)
- 将动态内存的起始地址传过去
- 没有返回值(void)
举例:在前面我们申请了40个字节的空间,地址是p,现在想要释放:
free(p);
在这之后,再写一个p=NULL;
,防止p称为野指针
3.free的头文件是stdlib.h
- 如果参数 ptr 指向的空间不是动态开辟的(比如 int a = 0; int* ptr = a;),那free函数的行为是未定义的。
- 如果参数 ptr 是NULL指针,则函数什么事都不做。
3. calloc和realloc
3.1 calloc
1.calloc 函数也用来动态内存分配。原型如下:
void* calloc (size_t num, size_t size);
它的含义是:开辟num个大小为size的空间,并且把空间的每个字节初始化为0。
2.calloc和malloc的区别是:
(1.calloc会将每个字节初始化为0.
(2.malloc是写总的空间大小,calloc是分开。
int main()
{
// 比如都申请10个整型的空间
int* ptr1 = (int*)malloc(10 * sizeof(int));
int* ptr2 = (int*)calloc(10, sizeof(int));
}
3.2 realloc
1.re再次,alloc开辟内存。realloc是调整
2.函数原型:
void* realloc (void* ptr, size_t size);
• ptr 是要调整的内存地址
• size 调整之后新大小
• 返回值为调整之后的内存起始位置。
• 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。
3.realloc在调整内存空间的是存在两种情况:
◦ 情况1:原有空间后面有足够大的空间(直接在原有内存之后追加空间)
◦ 情况2:原有空间后面没有足够大的空间(realloc函数会直接在内存的堆区寻找一块新的满足大小的空间;再将旧的数据拷贝到新的空间;最后释放旧的空间)
4.返回的值有可能是新地址,旧地址,空指针,我们不清楚什么情况。如果realloc用原来动态内存的空间来接收,如果后续空间不够,原来的数据都有可能搞丢。为了防止数据丢失,我们可以将返回值放在新的指针中。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)icalloc(10, sizeof(int)); //这里地址是p
if (p == NULL)
{