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语言】四个内存管理函数


前言

学习数组的时候一般会遇到这样一个问题,向一个数组中存入N个数,N<1000。由于N不确定,为了保证所有数都能存入数组不溢出,我们都会首先定义一个元素数量大于等于1000的数据,如下所示:

#include<stdio.h>
int main(void) {
	int arr[1000] = { 0 };
	int N = 0;
	int i = 0;
	printf("请输入数组的大小\n");
	scanf_s("%d", &N);
	printf("请输入%d个数\n", N);
	for (i = 0; i < N; i++)
		scanf_s("%d", &arr[i]);
	return 0;
}

这样做一个坏处就是可能会浪费内存空间,因为arr数组不一定能存的满。

很自然就能想到数组大小能不能动态定义?像这样:

#include<stdio.h>
int main(void) {
	int N;
	int i;
	int arr[N];
	printf("请输入数组的大小\n");
	scanf_s("%d", &N);
	printf("请输入%d个数\n", N);
	for (i = 0; i < N; i++)
		scanf_s("%d", &arr[i]);
	return 0;
}

编译会毫不犹豫地报错,提示是“应输入常量表达式”。
在这里插入图片描述
这是因为C89标准规定必须使用常量表达式指明数组长度。

虽然C99中可以使用变量指明数组长度,但一些编译器并不能很好地支持C99,其中就包括常用的VS2019。

总之,灵活地定义数组大小而不造成空间浪费的梦想是破碎了。

但是办法总是有的!!!办法就是今天的主角——malloc ()。

一、malloc

1、简介

隶属标准库: stdlib

原型: void *malloc(unsigned int size)

所以需要根据实际你需要的类型对其强制类型转换

返回值: 成功时,返回指向新分配内存的指针。失败时,返回空指针(NULL)

参数: size - 要分配的字节数,如malloc(10)表示申请10bytes的内存。

功能: 申请内存。需要内存的时候就用它申请,用完就扔掉了。也就是说malloc就好像一个渣男。

2、基本使用方法

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int* str;
	str = (int*)malloc(20);//申请20个字节的空间
	for (int i = 0; i < 5; i++)
	{
		*(str + i) = i;
	}
	for (int i = 0; i < 5; i++)
	{
		printf("%d\n", *(str + i));
	}
	/* 释放已分配的内存 */
	free(str);
	return(0);
}

0
1
2
3
4

3、使用malloc解决前言中的问题

使用malloc就可以做到需要多少空间就申请多少空间了,记得使用完要释放空间。

#include<stdio.h>
#include<stdlib.h>
int main(void) {
	int N = 0;
	int i = 0;
	printf("请输入数组的大小\n");
	scanf_s("%d", &N);
	int* arr = (int*)malloc(N * sizeof(int));
	printf("请输入%d个数\n", N);
	for (i = 0; i < N; i++)
		scanf_s("%d", &arr[i]);
	for (i = 0; i < N; i++)
		printf("%d ", arr[i]);
	free(arr);
	return 0;
}

请输入数组的大小
4
请输入4个数
23
89
52
14
23 89 52 14

二、free函数

free函数和malloc函数是形影不离的好兄弟。

1、简介

隶属标准库: stdlib

原型: void free(void *ptr)

返回值:

参数: ptr – 指针指向一个要释放内存的内存块

功能: 释放之前申请的内存(回收内存)

2、基本使用方法

如上所示

三、realloc函数

1、简介

隶属标准库: stdlib

原型: void *realloc(void *ptr, size_t size)

返回值: 该函数返回一个指针 ,指向重新分配大小的内存。如果请求失败,则返回 NULL。

参数:
ptr – 指针指向一个要重新分配内存的内存块,该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。如果为空指针,则会分配一个新的内存块,且函数返回一个指向它的指针。

size – 内存块的新的大小,以字节为单位。如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被释放,并返回一个空指针。

功能: 重新调整之前调用 malloc 或 calloc 所分配的 ptr 所指向的内存块的大小。

2、基本使用方法

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
	int* str;
	/* 最初的内存分配 */
	str = (int*)malloc(16);
	for (int i = 0; i < 4; i++)
	{
		*(str + i) = i;
		printf("%d ", *(str + i));
	}
	printf("\n");
	/* 重新分配内存 */
	str = (int*)realloc(str, 20);
	*(str + 4) = 4;
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", *(str + i));
	}

	free(str);
	return(0);
}

0 1 2 3
0 1 2 3 4

四、calloc函数

1、简介

隶属标准库: stdlib

原型: void *calloc(size_t nitems, size_t size)

返回值:

该函数返回一个指针,指向已分配的内存。如果请求失败,则返回 NULL。

参数:

nitems – 要被分配的元素个数。
size – 元素的大小。

功能:

分配所需的内存空间,并返回一个指向它的指针。malloc 和 calloc 之间的不同点是,malloc 不会设置内存为零,而 calloc 会设置分配的内存为零。

2、基本使用方法

#include <stdio.h>
#include <stdlib.h>
int main()
{
	int i, n;
	int* a;
	printf("要输入的元素个数:");
	scanf_s("%d", &n);
	a = (int*)calloc(n, sizeof(int));//申请n个int大小的空间
	printf("输入 %d 个数字:\n", n);
	for (i = 0; i < n; i++)
	{
		scanf_s("%d", a + i);
	}
	printf("输入的数字为:");
	for (i = 0; i < n; i++) {
		printf("%d ", *(a + i));
	}
	free(a);  // 释放内存
	return(0);
}

五、答疑

1、malloc与calloc的区别

malloc与calloc在内存分配时,最大的区别是后者在分配时会将内存置为0,前者不会,内存里仍保留着垃圾数据。

注意:malloc与calloc申请的都是连续内存空间

他们在用法上是相似的,以分配容纳5个int整型的空间为例,代码如下

malloc用法

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int* p = (int*)malloc(5 * sizeof(int));
	for (int i = 0; i < 5; i++)
	    //方法1
		//p[i] = i;
		//方法2
		*(p + i) = i;
	for (int i = 0; i < 5; i++)
		printf("%d ", p[i]);
    free(p);
	return 0;
}

0 1 2 3 4

calloc用法

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int* p = (int*)calloc(5, sizeof(int));
	for (int i = 0; i < 5; i++)
		p[i] = i;
	for (int i = 0; i < 5; i++)
		printf("%d ", p[i]);
		free(p);
	return 0;
}

0 1 2 3 4

2、为什么malloc、calloc、realloc函数都要和free函数配合使用?

我们都知道,就是malloc动态申请一块空间后,当不再需要的时候,需要将这块空间free掉,否则会出现内存泄漏。

什么是内存泄漏?

内存泄漏就是申请了内存使用完毕又不释放掉,导致其他程序无法再重复利用这块内存,这块内存相当于被浪费掉了(例如,原本4G的内存,有1G用了没有释放,此时你只有3G可以用了)。这浪费掉的内存就跟泄漏出去的水一样收不回来了。故叫做内存泄漏。

对于有操作系统的平台,即使你申请内存使用完忘了free也没关系,操作系统会监控每一块内存使用情况,你忘了它会帮你free。

但如果没有操作系统,如一些嵌入式平台,就没有自动回收机制了。这时候没用free就会导致内存泄漏。

内存泄漏有多可怕?
假如你要重复10k次分配10M的内存,如果每次使用完内存后都用free()释放,你的程序只需要占用10M内存就能运行;但如果你不用free(),那么你的程序结束之前就会吃掉100G的内存!你的系统很可能因此而崩溃。特别是嵌入式平台,内存空间本来就小,容不得内存泄漏。

因此为了防止出现内存泄漏,free必须与malloc、calloc、realloc函数形影不离。

3、malloc、calloc、realloc函数申请的是哪个地方的内存?

申请的是堆中的内存。

关于内存空间的分布,我会在另一篇文章中讲。


参考资料

1、5分钟看懂什么是 malloc https://zhuanlan.zhihu.com/p/105090421
2、深入 malloc 函数,带你真正理解内存分配。https://blog.csdn.net/liang19890820/article/details/120559090
3、malloc函数——一个低调的C语言学习者宝藏https://zhuanlan.zhihu.com/p/197918331
4、C语言malloc与calloc区别https://blog.csdn.net/qq_42759112/article/details/124744214
5、为什么动态内存分配申请后,还要再释放?https://www.sohu.com/na/469024940_121056793

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 10:54:41  更:2022-09-13 10:58:50 
 
开发: 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年5日历 -2024/5/19 14:55:43-

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