EP15:动态内存管理概述(c语言)malloc,calloc,realloc函数的介绍使用及柔性数组的介绍

本文主要是介绍EP15:动态内存管理概述(c语言)malloc,calloc,realloc函数的介绍使用及柔性数组的介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

序言:在c语言中,什么是动态内存

1.malloc函数简述

1.1free函数

1.2 malloc函数

2.calloc函数简述

3.对malloc函数与calloc函数进行总结

3.1 不同点 (函数参数上)

3.2 相同点(函数使用步骤上)

4.重要的realloc函数的简介与使用

4.1 对realloc函数的使用进行简述

4.2 以calloc函数进行开辟为例,扩容的公式

4.2.1calloc函数扩展内存空间的方式

5.柔性数组 

5.1 柔性数组概述

5.2 柔性数组的使用

ps:"->"操作符和"."(点)操作符的使用


如果学习方向是c++方向那么c语言有三个板块的知识是非常重要的. 1:指针 2:结构体 3;动态内存管理.

序言:在c语言中,什么是动态内存

C语言中的动态内存是指在程序运行时,根据需要动态地分配内存空间的一种内存管理方式。与静态内存相比,动态内存的大小和生命周期都可以在程序运行时动态地确定和调整,因此更加灵活。C语言中提供了四个函数:malloc、calloc、realloc和free,用于动态地分配和释放内存空间。其中,malloc和calloc用于分配内存空间,realloc用于调整已分配内存空间的大小,free用于释放已分配的内存空间。动态内存的使用需要引用头文件<stdio.h>或<malloc.h>。

在本篇文章中,我们将着重简述何为malloc函数,calloc函数,free,以及柔性数组

1.malloc函数简述

1.1free函数

C语言提供了另外⼀个函数free,专门是用来做动态内存的释放和回收的,函数原型如下:

 void free (void* ptr);

free函数用来释放动态开辟的内存。

 但凡涉及到动态内存的开辟,释放空间这一步作为最后一步绝对是不可或缺的.

1.2 malloc函数

函数头文件: #include <stdlib.h>

函数参数: void* malloc (size_t size);

函数作用: 用于开辟动态内存

从代码示例看函数的具体使用方法

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    int* p = (int*)malloc(10 * sizeof(int));//1.动态内存的开辟(指针p所指向的是malloc函数开辟空间的起始地址)

     malloc():括号里面要写的是开辟多少大小的内存空间,一般用:任意整数*sizeof(整型)
    if (p == NULL)
    {
        perror("malloc");
        return 1;
    }


    int i = 0;
    for (i = 0; i < 10; i++)//2.对动态内存开辟的空间进行访问

    {
        *(p + i) = i;//使用指针p去访问malloc开辟的空间里面的元素,再解引用赋值给i
    }


    for (i = 0; i < 10; i++)//3.对开辟的空间中的内容进行打印
    {
        printf("%d ",i );//将刚才访问的空间里面存储的数据打印出来
    }


    free(p);//4.对开辟的空间进行回收
    p=NULL;
    return 0;
 }

为啥要这么写:  int* p = (int*)malloc(10 * sizeof(int));

解释:由函数参数 void* malloc (size_t size);可知malloc函数一个空指针类型的函数,但是由于空指针是不可以直接用于指针的运算的,所以我们要将它强制类型转换成我们想要的类型.

一点联想:这一点让我想起了qsort函数,感觉void*类型的指针都要进行这样的操作,可以在这里留意一下并且进

行相关的知识迁移以便日后遇到相似知识点的学习

2.calloc函数简述

总而言之,calloc函数的使用方法以及功能和malloc函数基本一致

函数头文件: #include <stdlib.h>

函数参数: void* calloc (size_t num, size_t size);

函数作用: 用于开辟动态内存

从代码示例看函数的具体使用方法

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    int* p = calloc(10, sizeof(int));//1.动态内存的开辟
    if (p == NULL)
    {
        perror("calloc");
        return 1;
    }


    int i = 0;//2.对动态内存开辟的空间进行访问
    for (i = 0; i < 10; i++)
    {
        *(p + i) = i;
    }


    for (i = 0; i < 10; i++)//3.对开辟的空间中的内容进行打印
    {
        printf("%d ", *(p + i) );
    }


    free(p);//4.对开辟的空间进行回收
    p = NULL;

    return 0;
}

3.对malloc函数与calloc函数进行总结

3.1 不同点 (函数参数上)

以上述两段代码为例

malloc函数是:int* p = (int*)malloc(10 * sizeof(int));

calloc函数是: int* p = (int*)calloc(10, sizeof(int));

观察上述两段代码,其实也没啥不同点,就是把函数括号里面我们想要开辟的空间的那个表达式把逗号改成了*号的区别嘛

3.2 相同点(函数使用步骤上)

首先要明确的是它们都要进行强制类型转换转换成我们想要的指针类型.

最重要的是,它们是使用步骤可以分成四步

1.动态内存的开辟

2.对动态内存开辟的空间进行访问

3.对开辟的空间中的内容进行打印

4.对开辟的空间进行释放

简化一下就是: 1.开辟 2.访问 3.使用 4.释放

这两个函数在这四个步骤上的写法是一摸一样,没有任何区别的.将此四部先后逻辑顺序理清并进行适当的记忆这两个动态内存函数便可以说是掌握了.

所以此二者等价

4.重要的realloc函数的简介与使用

4.1 对realloc函数的使用进行简述

 在本文的开头阐述过何为动态内存"...动态内存的大小和生命周期都可以在程序运行时动态地确定和调整,因此更加灵活。..."

故而没有realloc函数的介入很难把一段可正常运行的代码叫做"动态内存管理"

函数头文件: #include <stdlib.h>

函数参数: void* realloc (void* ptr, size_t size);

对函数参数的解释: void*ptr就是要进行扩展的对象,size_t size就是要将被扩展的扩展至管理员预期的空间

函数作用: 用于动态内存的扩展,要和malloc函数或者calloc函数进行联合使用

具体且形象的讲解realoc函数的作用:

realloc的作用就是将原本malloc和calloc开辟的空间扩大到多少
举个例子就是说如果malloc或calloc是一段单向路上不与起点重合的一个质点,calloc就是另外一个质点
用calloc质点到起点的距离减去malloc,calloc质点所在的距离便是calloc函数所追加的空间

如图


 

从代码示例看函数的具体使用方法

就是在malloc函数和calloc函数原先的使用步骤上加上扩容这一步

1.动态内存的开辟

2.对动态内存开辟的空间进行访问

3,对malloc函数或calloc函数开辟的空间进行扩容

4.对开辟的空间中的内容进行打印

5.对开辟的空间进行释放

总结下来就是 1.开辟 2.访问 3,扩容 4.使用 5.释放

4.2 以calloc函数进行开辟为例,扩容的公式

    int* ptr = (int*)realloc(p, 15 * sizeof(int));//扩展开辟空间
    if (p != NULL)
    {
        p = ptr;
    }
    else
    {
        perror("errno");
        return 1;
    } 

为什么这么写: int* ptr = (int*)realloc(p, 15 * sizeof(int));

这里便涉及到calloc函数扩展内存空间的方式了

4.2.1calloc函数扩展内存空间的方式

情况1:扩展失败,返回NULL,于是便有了 

 else
    {
        perror("errno");
        return 1;
    } 

情况2;扩展成功了,于是便有了

if (p != NULL)
    {
        p = ptr;
    }

扩展成功方式1:

在malloc函数或者calloc函数开辟好的空间后进行扩容,如果没有足够的空间进行扩大时候,此时的calloc函数会在堆区中重新选择一块大小满足需求的空间,同时将旧空间中的旧数据连同着一块拷过来,这也是为啥虽然上述代码  int* ptr = (int*)realloc(p, 15 * sizeof(int));虽然写的是15 * sizeof(int)实际上只是扩展了5*sizeof(int)大小的空间.然后释放就空间,同时返回新的空间.

扩展成功方式1:

若空间大小足够,则在已经开辟好的空间直接进行追加空间进行扩展,扩大空间后,直接返回就空间的起始地址.

4.3 从示例看realloc函数的具体用法 

根据上面总结的五个步骤来写:  1.开辟 2.访问 3,扩容 4.使用 5.释放

int main()// 开辟 访问   扩容 使用 释放
{
    //开辟
    int* p = (int*)calloc(10, sizeof(int));
    if (p == NULL)
    {
        perror("calloc");
        return 1;
    }

    //访问
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        *(p + i) = i;
    }

    //扩容
     int* ptr = (int*)realloc(p, 15 * sizeof(int));//扩展开辟空间
    if (p != NULL)
    {
        p = ptr;
    }
    else
    {
        perror("errno");
        return 1;
    }

    //使用
    for (i = 0; i < 10; i++)
    {
        printf("%d ", *(p + i) );
    }

    

    //释放
    free(p);
    p = NULL;

    return 0;
}

ps:其实realloc函数除了调整空间外,也可以实现和malloc或者realloc函数一样的功能

int*p=(int*)realloc(NULL,1o*sizeof(int));等价于malloc或者calloc函数,只是一般不这么去写.

5.柔性数组 

5.1 柔性数组概述

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

结构体成员的特点

• 结构中的柔性数组成员前面必须至少一个其他成员。

• sizeof 返回的这种结构大小不包括柔性数组的内存。

• 包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

5.2 柔性数组的使用

以malloc函数为例,柔性数组的使用依旧遵循上述的五个步骤,不同的是要先创建一个结构体

1. 开辟 2.访问 3.扩容 4.使用 5.释放

struct st
{
    char c;
    int n;
    int arr[0];
};


int main()
{
    struct st* ps = (struct st*)malloc(sizeof(struct st) + 10 * sizeof(int));//1.开辟
    //前面的sizeof(struct st)是计算此结构体本来的大小
    //后面的 10 * sizeof(int) 意思是将柔性数组成员开辟成多少大小的

    if (ps == NULL)
    {
        perror("malloc");
        return 1;
    }

    ps->c = 'w';//2.访问
    ps->n = 100;
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        ps->arr[i]=i;//也可以这么写 QUESTION2;点操作符和箭头操作符的区别,在那些情况下一般用什么的总结归纳
    }

    struct st* ptr = (struct st*)realloc(ps, sizeof(struct st) + 15 * sizeof(int));//3.扩容
    if (ptr != NULL) 
    {
        ps = ptr;
    }
    else
    {
        perror("realloc");
        return 1;
    }

    for (i = 0; i < 10; i++)//4.使用
    {
        printf("%d ", i);
    }
    printf("\n");
        printf("%c \n", ps->c);
        printf("%d \n", ps->n);


    free(ps);//5.释放
    ps = NULL;
    return 0;
}

ps:"->"操作符和"."(点)操作符的使用

1.点操作符的使用情况

直接使用

  struct st
{
    int a;
    int b;
};
int main1()
{
    struct st s = { .a = 10 , .b=20 };
    printf("%d %d ", s.a, s.b);
    return 0;
}

2.->的使用情况

由柔性数组的实例情况使用可知,在"结构体+指针"的情况下如果要使用指针对结构体中某一个成员变量进行访问,那么就是"指针->结构体成员变量名=程序员想要赋的值".

封面如下

 

这篇关于EP15:动态内存管理概述(c语言)malloc,calloc,realloc函数的介绍使用及柔性数组的介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/492392

相关文章

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>