动态内存的开辟

简介: 🐰动态内存管理 🐰malloc 🐰calloc🐰realloc 🐰free 🐰动态开辟常见的错误

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

目录

🐰动态内存管理

🐰malloc

🐰calloc

🐰realloc

🐰free

🐰动态开辟常见的错误


🐰动态内存管理

其实我们创建数组的时候,系统为我们就是开辟了一段连续的空间(这个空间一般是在栈区开辟的),现在我们可以自己开辟一段空间。与动态开辟相关的函数:malloc free calloc realloc

注意:数组离开作用域时,系统会自动释放这段空间,如果我们自己动态开辟的空间,离开作用域时,系统是不会帮我们释放这段空间的,如果要求释放这段动态开辟的空间,我们就需要使用free函数去释放。

🐰malloc

malloc用于动态开辟内存,引用的头文件是#include<stdlib.h>

malloc的原型:

void* malloc (size_t size);

size_t size:开辟的字节数

注意:返回的类型是void*类型,如果想要使用这段空间,就必须强制性转化为自己想使用的类型,例如:int* p=(int*)malloc(20);这就是开辟了20个字节,然后把20个字节空间的首地址赋值给了p。

malloc的使用:

malloc开辟成功会返回开辟好的空间的首地址, malloc如果申请内存失败会返回空指针NULL,所以我们开辟好空间的话,需要去判断一下

1. #include<stdio.h>
2. #include<stdlib.h>
3. #include<errno.h>
4. #include<string.h>
5. int main()
6. {
7. int *p=(int *)malloc(20);//开辟了20个字节的空间
8. if(p==NULL)
9.     {
10. printf("%s\n",strerror(errno));//打印开辟失败的原因
11.     }
12. free(p);
13.     p=NULL;
14. return 0;
15. }

malloc开辟空间,不初始化,里面存放的随机值

1. #include<stdio.h>
2. #include<stdlib.h>
3. int main()
4. {
5. int *p=(int *)malloc(20);//开辟了20个字节的空间
6. for(int i=0;i<5;i++)
7.     {
8. printf("%d ",*(p+i));
9.     }
10. //使用
11. for(int i=0;i<5;i++)
12.     {
13.         *(p+i)=i+1;
14.     }
15. for(int i=0;i<5;i++)
16.     {
17. printf("%d ",*(p+i));
18.     }
19. free(p);
20.     p=NULL;
21. return 0;
22. }

🐰calloc

calloc用于动态开辟内存,区别于malloc的是,calloc会初始化开辟的空间,将开辟的空间全部初始化为0,引用的头文件是#include<stdlib.h>

calloc的原型:

void* calloc (size_t num, size_t size);

size_t num:开辟的个数

size_t size:开辟的类型的大小

注意:返回的类型是void*类型,如果想要使用这段空间,就必须强制性转化为自己想使用的类型,例如:int* p=(int*)calloc(20,sizeof(int));这就是开辟了20个整形的空间,然后把20个整形空间的首地址赋值给了p。

calloc的使用:

calloc开辟空间,初始化,里面存放的0

1. #include<stdio.h>
2. #include<stdlib.h>
3. int main()
4. {
5. 
6. int *p=(int *)calloc(20,sizeof(int));//开辟了20个int类型的空间
7. for(int i=0;i<20;i++)
8.     {
9. printf("%d ",*(p+i));
10.     }
11. free(p);
12.     p=NULL;
13. return 0;
14. }

🐰realloc

realloc用于原空间不足继续开辟更大的空间,引用头文件为#include<stdlib.h>

realloc的原型:

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

void* ptr:原空间的首地址

size_t size:开辟新空间的大小

注意:realloc开辟空间会遇到两种情况

1.如果原空间后面空间充足

在原空间后面继续开辟空间(返回的地址与原来的地址相同)

2.如果原空间后面空间不足

(1)realloc会找更大的空间

(2)将原来的数据拷贝到新空间

(3)释放原来的旧的空间

(4)返回新空间的地址(返回的地址与原来的地址不同)

realloc的使用:

1. #include<stdio.h>
2. #include<stdlib.h>
3. #include<string.h>
4. #include<errno.h>
5. int main()
6. {
7. int *p=(int *)malloc(20);//开辟了20个int类型的空间
8. if(p==NULL)
9.     {
10. printf("%s\n",strerror(errno));
11.     }
12. for(int i=0;i<5;i++)
13.     {
14. printf("%d ",*(p+i));
15.     }
16. int* pc=(int*)realloc(p,sizeof(p)*2);//在原空间进行扩展
17. if(pc!=NULL)
18.     {
19.         p=pc;//把空间首地址还是赋给p
20. for(int i=0;i<10;i++)
21.         {
22. printf("%d ",*(p+i));
23.         }
24.     }
25. else
26.     {
27. printf("realloc:%s\n",strerror(errno));//如果开辟失败,打印原因
28.     }
29. free(p);
30.     p=NULL;
31. return 0;
32. }

🐰free

free用于释放动态开辟的空间,引用头文件#include<stdlib.h>

free的原型:

void free (void* ptr);

void* ptr:动态开辟空间的首地址

注意:释放的空间一定是动态开辟的(就是在堆上开辟的),不然free是不起作用的。

 

free的使用:

1. #include<stdio.h>
2. #include<stdlib.h>
3. int main()
4. {
5. int* p=(int *)malloc(20);//开辟了20个字节的空间
6. free(p);//将20个字节的空间还给了系统
7.     p=NULL;//如果不把p置为空指针,那么p就是野指针
8. return 0;
9. }

🐰动态开辟常见的错误

可能开辟空间失败,然后再去解引用会发生错误,所以malloc的返回值要去判断和越界访问。

1. #include<stdio.h>
2. #include<stdlib.h>
3. #include<string.h>
4. #include<errno.h>
5. int main()
6. {
7. int* p=(int*)malloc(20);
8. //可能开辟空间失败,然后再去解引用会发生错误,所以malloc的返回值要去判断
9. //所以我们需要判断
10. if(p==NULL)
11.     {
12. printf("%s",strerror(errno));//打印发生的错误
13. return; 
14.     }
15. for(int i=0;i<5;i++)
16.     {
17.         p[i]=i;
18.     }
19. 
20. //越界访问
21. for(int i=0;i<10;i++)//只开辟了5个int类型的空间,却访问了10个int类型的空间
22.     {
23.         p[i]=i;
24.     }
25. 
26. free(p);
27.     p=NULL;
28. return 0;
29. }

对非动态开辟的空间进行释放

1. #include<stdio.h>
2. #include<stdlib.h>
3. int main()
4. {
5. int arr[10]={1,2,3};
6. int *p=arr;
7. free(p);//对非动态开辟的空间进行释放
8. return 0;
9. }

释放一部分动态开辟的空间

1. #include<stdio.h>
2. #include<stdlib.h>
3. int main()
4. {
5. int* p=(int*)malloc(40);
6. for(int i=0;i<10;i++)
7.     {
8.         p[i]=i;
9.     }
10.     p++;//p指向的就不是动态开辟空间的首地址
11. free(p);//使用free释放一块动态开辟内存的一部分,不是从开辟空间的首地址开始释放的
12.     p=NULL;
13. return 0;
14. }

对一块空间多次释放

1. #include<stdio.h>
2. #include<stdlib.h>
3. int main()
4. {
5. int* p=(int*)malloc(40);
6. free(p);
7. //p=NULL;//如果释放了指针之后,再次释放是不会出错的,因为指针为空时,free不会做出任何反应
8. free(p);//重复释放
9.     p=NULL;
10. return 0;
11. }

不能对空指针进行解引用操作

1. #include<stdio.h>
2. #include<string.h>
3. #include<stdlib.h>
4. void GetMemory(char* str)
5. {
6.     str=(char *)malloc(20);
7. //str是p的临时拷贝,malloc动态开辟的空间,将首地址给了str,p仍然是空指针
8. }
9. int main()
10. {
11. char* p=NULL;
12. GetMemory(p);
13. strcpy(p,"hello world");//这里对空指针进行了解引用操作
14. printf("%s",p);
15. return 0;
16. }

野指针问题

1. #include<stdio.h>
2. #include<string.h>
3. #include<stdlib.h>
4. char* GetMemory(void)
5. {
6. char str[]="hello world";
7. //返回栈区空间的问题
8. //GetMemory函数内部创建的数组str,str是临时创建,虽然返回了str数组的首地址,但是离开GetMemory函数之后,str内存会归还给系统,p的值虽然还是str数组的首地址,但是str空间已经归还给系统,str再去访问就是非法访问了。(栈区开辟的空间,离开作用域,栈区开辟的空间会被销毁)
9. return str;
10. }
11. int main()
12. {
13. char* p=NULL;
14.     p=GetMemory();
15. printf("%s",p);
16. return 0;
17. }

注:一定要记住

栈区:局部变量,函数形参

堆区:动态管理的空间(malloc,realloc,calloc,free)

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

🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸

相关文章
|
6月前
|
编译器 C语言 C++
【C语言】realloc()函数详解(动态内存开辟函数)
【C语言】realloc()函数详解(动态内存开辟函数)
91 0
|
6月前
|
编译器 C++
C/C++动态内存开辟(详解)
C/C++动态内存开辟(详解)
|
存储 编译器 C语言
C语言进阶第六课-----------字符分类函数和内存的开辟 2
C语言进阶第六课-----------字符分类函数和内存的开辟
|
C语言
C语言进阶第六课-----------字符分类函数和内存的开辟 1
C语言进阶第六课-----------字符分类函数和内存的开辟
|
程序员 编译器 C语言
动态内存函数,内存开辟,柔性数组(超详细)
动态内存函数,内存开辟,柔性数组(超详细)
72 0
|
Unix 程序员 Linux
【OSTEP】动态内存开辟 | 内存API常见错误 | UNIX: brk/sbrk 系统调用 | mmap创建匿名映射区域 | mmap创建以文件为基础的映射区域
【OSTEP】动态内存开辟 | 内存API常见错误 | UNIX: brk/sbrk 系统调用 | mmap创建匿名映射区域 | mmap创建以文件为基础的映射区域
265 0
|
5月前
|
C语言
C语言学习记录——动态内存开辟常见的错误
C语言学习记录——动态内存开辟常见的错误
33 1
|
6月前
|
编译器 C++
内存对齐与内存开辟。结构体(struct),位段,枚举类型(enum),联合体(union)。
内存对齐与内存开辟。结构体(struct),位段,枚举类型(enum),联合体(union)
38 1
|
5月前
|
C语言
动态内存开辟(下)
动态内存开辟(下)
22 0
|
5月前
|
编译器 C语言
动态内存开辟(上)
动态内存开辟(上)
25 0