IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c语言十七:动态内存申请 -> 正文阅读

[C++知识库]c语言十七:动态内存申请

一 动态内存申请

  1. 数组的长度是预先定义好的,在整个程序中固定不变;
  2. 但在实际应用中,往往有这种情况,所需要的内存空间取决于实际输入的数据,而无法预先确定
  3. 为了解决上面的问题,C语言提供了一些内存管理函数,这些内存管理函数可以安装需要动态的分配内存空间,也可以把不再使用的内存空间回收再利用

二 静态分配内存和动态分配内存

2.1 静态分配内存

  1. 在程序编译或运行过程中,按事先规定好的大小分配内存空间的分配方式;
  2. 必须事先知道所需空间的大小;
  3. 空间是分配在栈区或全局变量区的;
  4. 按计划分配

2.2 动态分配内存

  1. 在程序运行过程中按需要自由分配所需空间;
  2. 按需分配;
  3. 空间是分配在堆区的,一般使用特点函数来分配

三 动态内存申请的相关函数

3.1 分配内存空间函数 malloc

函数功能: 在内存的动态存储器(堆区)中分配一块长度为size字节的连续内存空间,用来存放类型说明符指定的数据类型
函数原型: void *malloc(unsigned int num_bytes);
				形参num_bytes是需要申请内存空间的字节数
调用形式: (类型说明符*) malloc(size)
返回值:
		分配成功:分配的内存空间的起始地址
		分配失败:NULL
注意事项:
		1. 对malloc的返回值一定要强制类型转换;
		2. malloc申请的内存空间的内容不确定,一般需要使用memset进行清空;
		3. 调用malloc后,一定要判断一下,是否申请内存成功;
		4. 如果多次malloc申请的内存,第一次和第二次申请的内存不一定连续;

3.2 free函数 (释放内存函数)

函数说明:free函数释放ptr指向的内存
函数定义:void free(void *ptr)
注意事项:ptr指向的内存必须是malloc,calloc,relloc动态申请的内存

3.3 案例一:从堆区申请一个int类型的空间

[root@ansible9 ~]# cat  test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int arg, char *argv[])
{
	int *p=NULL;
	p=(int *)malloc((int)sizeof(int));
	if(p==NULL)
	{
		printf("malloc err\n");
		return 1;
	}
	printf("用malloc申请的内存空间中的内容是不确定的:%d\n",*p);
	memset(p,0,(int)sizeof(int));
	printf("用memset清0后的内存空间中的内容是:%d\n",*p);
	printf("请输入一个int数值:");
	scanf("%d",p);
	printf("%d\n",*p);
	free(p);
}
[root@ansible9 ~]# ./a.out 
用malloc申请的内存空间中的内容是不确定的:0
用memset清0后的内存空间中的内容是:0
请输入一个int数值:111
111

3.4 案例二:从堆区申请一个数组,数组的大小由用户决定

步骤:

  1. 从键盘获取要申请的数组的大小;
  2. 根据大小,从内存堆区申请空间;
  3. 对空间读写操作;
  4. 释放该空间;
[root@ansible9 ~]# cat test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int arg, char *argv[])
{
	printf("请输入数值元素的个数:");
	int n=0;
	scanf("%d",&n);
	printf("将要为元素个数为%d个的数组申请内存空间\n",n);
	int *p=NULL;
	p=(int *)malloc(n*(int)sizeof(int));
	if(p==NULL)
	{
		perror("malloc error!");
		return 1;
	}
	memset(p,0,n*(int)sizeof(int));
	int i=0;
	printf("请输入%d个int数组",n);
	for(i=0;i<n;i++)
	{
		scanf("%d",p+i);
	}
	for(i=0;i<n;i++)
	{
		printf("%d\n",p[i]);
	}
	free(p);
}
[root@ansible9 ~]# ./a.out 
请输入数值元素的个数:5
将要为元素个数为5个的数组申请内存空间
请输入5个int数组10 20 30 40 50 60 70 80 
10
20
30
40
50

3.5 calloc函数

函数原型:void * calloc(size_t nmemb, size_t size);
			参数: size_t是无符号整形,是在头文件中用typeof定义出来的
			返回值:申请失败:返回NULL;申请成功:返回申请的内存的首地址
函数功能:在内存的堆区,申请nmemb块,每块大小为size字节的连续内存空间
注意事项:
			1. calloc函数申请的内存空间已经自动被清0了,不用再用memset清0;
			2. calloc函数申请的内存空间字节数为nmemb和size的乘积;
[root@ansible9 ~]# cat test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int arg, char *argv[])
{
	printf("请输入数值元素的个数:");
	int n=0;
	scanf("%d",&n);
	printf("将要为元素个数为%d个的数组申请内存空间\n",n);
	int *p=NULL;
	p=(int *)calloc(n, (int)sizeof(int));
	if(p==NULL)
	{
		perror("calloc error!");
		return 1;
	}
	int i=0;
	printf("请输入%d个int数组",n);
	for(i=0;i<n;i++)
	{
		scanf("%d",p+i);
	}
	for(i=0;i<n;i++)
	{
		printf("%d\n",p[i]);
	}
	free(p);
}
[root@ansible9 ~]# ./a.out 
请输入数值元素的个数:5
将要为元素个数为5个的数组申请内存空间
请输入5个int数组10 20 30 40 50 60 70
10
20
30
40
50

3.5 realloc函数(重新申请内存空间)

函数原型:void* realloc(void* s, unsigned int newsize);
形参:s原先开辟内存的地址           newsize:新申请内存的大小
返回值:新申请内存的首地址
函数功能:在原先s执行的内存基础上重新申请内存,新的内存大小为newsize字节,如果原先内存后面有足够大的空间就追加;如果没有则realloc函数会在内存堆区找一个newsize字节大小的空间来申请,将原先内存中的数据拷贝过来,然后释放原先的内存,最后返回新内存的地址
[root@ansible9 ~]# cat test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int arg, char *argv[])
{
	printf("请输入数值元素的个数:");
	int n=0;
	scanf("%d",&n);
	printf("将要为元素个数为%d个的数组申请内存空间\n",n);
	int *p=NULL;
	p=(int *)calloc(n, (int)sizeof(int));
	if(p==NULL)
	{
		perror("calloc error!");
		return 1;
	}
	int i=0;
	printf("请输入%d个int数组元素",n);
	for(i=0;i<n;i++)
	{
		scanf("%d",p+i);
	}
	for(i=0;i<n;i++)
	{
		printf("%d\n",p[i]);
	}
	printf("想要为数组增加几个元素:");
	int m=0;
	scanf("%d",&m);
	printf("您想要增加%d个元素\n",m);
	p=(int *)realloc(p,(n+m)*(int)sizeof(int));
	if(p==NULL)
	{
		perror("calloc error!");
		return 1;
	}
	printf("请输入%d个新int数组元素",m);
	for(i=n;i<(m+n);i++)
	{
		scanf("%d",p+i);
	}
	for(i=0;i<(n+m);i++)
	{
		printf("%d\n",p[i]);
	}
	printf("数组现有%d个元素\n",(n+m));
	int h=0;
	printf ("想减少几个元素:");
	scanf("%d",&h);
	printf("您想减少%d个元素\n",h);
	p=(int *)realloc(p,(n+m-h)*(int)sizeof(int));
	if(p==NULL)
	{
		perror("calloc error!");
		return 1;
	}
	for(i=0;i<(n+m-h);i++)
	{
		printf("%d\n",p[i]);
	}
	free(p);
}
[root@ansible9 ~]# ./a.out 
请输入数值元素的个数:3
将要为元素个数为3个的数组申请内存空间
请输入3个int数组元素10 20 30
10
20
30
想要为数组增加几个元素:2
您想要增加2个元素
请输入2个新int数组元素40 50
10
20
30
40
50
数组现有5个元素
想减少几个元素:4
您想减少4个元素
10

四 动态内存申请的注意事项

4.1 指向堆区的指针变量不要随意更改指向,会导致calloc申请的内存空间泄漏

[root@ansible9 ~]# cat test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int arg, char *argv[])
{
	int *p = (int *)malloc(4*(int)sizeof(int));
	int num=10;
	p=&num;
}

4.2 不要操作已经释放的空间,因为该空间内容已经不能确定了

[root@ansible9 ~]# cat test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int arg, char *argv[])
{
	int *p = (int *)malloc((int)sizeof(int));
	memset(p,0,(int)sizeof(int));
	*p=100;
	free(p);
	printf("%d\n",*p);
}

4.3 不要对堆区空间重复释放

[root@ansible9 ~]# cat test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int arg, char *argv[])
{
	int *p = (int *)malloc((int)sizeof(int));
	memset(p,0,(int)sizeof(int));
	*p=100;
	free(p);
	free(p);
}
[root@ansible9 ~]# gcc -Wall test.c
[root@ansible9 ~]# ./a.out 
free(): double free detected in tcache 2
Aborted (core dumped)

4.4 如何防止对堆区空间重复释放?

在这里插入图片描述

四 内存泄漏

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-15 22:13:21  更:2022-03-15 22:16:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:50:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码