0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

周立功:动态分布内存——malloc()函数与calloc()函数

AGk5_ZLG_zhiyua 来源:互联网 作者:佚名 2017-08-22 17:01 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

周立功教授数年之心血之作《程序设计与数据结构》,电子版已无偿性分享到电子工程师与高校群体,在公众号回复【程序设计】即可在线阅读。书本内容公开后,在电子行业掀起一片学习热潮。经周立功教授授权,本公众号特对本书内容进行连载,愿共勉之。

第一章为程序设计基础,本文为1.9.1 malloc()函数和1.9.2 calloc()函数。

》》》》 1.9 动态分配内存

首先回顾一下内存分配,所有程序都必须预留足够的内存存储程序使用的数据,这些内存中有些是自动分配的。比如,声明“int iNum;”为一个int类型的值预留了足够的内存,或显式指定分配一定数量的内存,“int pData[20];”声明预留了20个内存位置,每个位置存储的是int类型的值。声明还为内存提供了标识符,因此可以使用iNum或pData识别数据。静态数据在程序载入内存时分配的,自动数据是在程序执行时分配的,并在程序离开时销毁。但C能做的远不止这些,可以在程序运行时请求所需要的内存大小。

程序在运行时分配的内存空间称之为“堆”的存储池,虽然计算机在硬件上不直接支持堆,但C函数库(stdlib.h)分别提供了用于动态内存分配和释放的函数malloc()和free(),即在运行时根据需要创建一个存储单元,在不需要时释放。

》》》 1.9.1 malloc()函数

malloc()函数原型如下:

void *malloc(unsigned int size);

其中,void *表示该函数是指针函数,size为所需内存的字节数,可以用sizeof运算符计算每个元素所需要的空间数量和所有元素需要内存的字节数。如果分配成功,虽然malloc()不会为分配的内存赋名,但它确实返回了动态分配内存块的首字节地址。因此可以将该地址赋给一个指针变量,并使用指针变量访问这块内存。如果分配不成功或内存不足,则返回空指针NULL。因此在使用它返回的指针之前,一定要先检查返回值,否则可能会导致程序非正常终止。比如:

int *pi = malloc(sizeof(int));

if(pi != NULL){

// 指针没有问题

}else{

// 无效的指针

}

malloc()函数可用于返回指向数组的指针、指向结构的指针等,所以通常该函数的返回值会被强制转换为匹配的类型,但从C99版本开始,void *类型的指针不需要强制转换地赋给所有的指针类型变量。

当编写程序时,常常很难为数组估计合适的大小,较为方便的做法是等到程序运行时,再来确定数组的实际大小。其方法是用malloc()在程序执行期间为数组分配空间,然后通过指向数组第一个元素的指针访问数组。假设正在编写的程序需要n个整数构成的数组,这里的n可以在程序执行期间计算出来。首先需要声明指针变量:

int * pi, n;

一旦n的值已知,就让程序调用malloc()函数为数组分配存储空间:

pi = malloc(n * sizeof(int));

if(pi == NULL) return -1;

当pi指向分配动态分配的内存块时,就可以忽略pi是指针的事实,将它作为数组名使用,这是C语言数组和指针形成紧密关系的所带来的便利。由于数组名是该数组首元素的地址,如果让pi指向这个块的首元素,便可以象使用数组名一样使用它。即可以使用pi[0]访问该块的首元素,pi[1]访问第2个元素,以此类推。比如,使用下列循环对pi指向的数组进行初始化:

for(i = 0; i 《 n; i++) pi[i] = 0;

动态内存分配可以提供更多的灵活性,比如:

char *pcStr;

char *pcStr = malloc(strlen(“OK!”) + 1);

strcpy(pcStr, “OK!”);

在这里,使用strlen()计算字符串的长度,一定要记得加上结束符NUL。为何不用sizeof呢?因为szieof会返回数组和指针的长度,而不是字符串的长度。

》》》 1.9.2 calloc()函数

虽然可以用malloc()函数为数组分配内存,但C语言提供了一种更好用的calloc()函数,其函数原型如下:

void *calloc(size_t nmenb, size_t size);

calloc()函数为nmemb个元素的数组分配内存空间,其中,每个元素的长度都是size个字节。如果要求的空间无效,那么此函数返回指针。在分配了内存之后,calloc()函数会通过将所有位设置为0的方式进行初始化。比如,调用calloc()函数为n个整数的数组分配存储空间,且保证所有整数初始化为0。比如:

pi = calloc(n, sizeof(int));

因为calloc()函数会清楚分配的内存,而malloc()函数不会,所以可以调用以“1”作为第一个实参的calloc()函数,为任何类型的数据项分配空间。比如:

struct point{ int x, y;} *pi;

pi = calloc(1, sizeof(struct point));

在执行此语句后,pi将指向一个结构体,且此结构体的成员x和y都会被设为0。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 周立功
    +关注

    关注

    38

    文章

    130

    浏览量

    38575
  • 大数据
    +关注

    关注

    64

    文章

    9029

    浏览量

    143071
  • malloc
    +关注

    关注

    0

    文章

    53

    浏览量

    346

原文标题:周立功:动态分布内存——malloc()函数与calloc()函数

文章出处:【微信号:ZLG_zhiyuan,微信公众号:ZLG致远电子】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    为什么单片机中很少使用malloc,而PC程序频繁使用呢?

    使用 malloc)变得不太适用,因为动态内存分配可能导致内存碎片,造成内存不足或系统崩溃。 PC:现代PC的内存资源相对丰富,RAM通常在
    发表于 11-20 06:55

    RTThread线程退出后rt_malloc动态创建的资源没有释放怎么解决?

    测试过程中,在一个线程中用rt_malloc动态创建4KB的资源,在线程运行过程中用rt_thread_delete()使线程退出,用memtrace查看内存分配情况,动态创建的4KB
    发表于 10-13 07:06

    rt_malloc_align函数内存越界问题怎么解决?

    ; } 代码如上所示。 条件:align = 4,rt_malloc申请到的内存地址为0x2000001,sizeof(void*) = 4 结果: align_ptr = 0x2000004 则
    发表于 09-22 08:30

    详解hal_entry入口函数

    当使用RTOS时,程序从main函数开始进行线程调度;当没有使用RTOS时,C语言程序的入口函数main函数调用了hal_entry函数。由于我们新建的工程是没有选用RTOS的,因此,
    的头像 发表于 07-25 15:34 1664次阅读

    C语言中的内联函数与宏

    在C编程中,内联函数和宏都用于避免函数调用的开销并编写可复用的逻辑部分,但它们在工作方式和安全性方面存在显著差异。
    的头像 发表于 07-25 15:10 1718次阅读
    C语言中的内联<b class='flag-5'>函数</b>与宏

    基于 IAR Embedded Workbench 的自研 MCU 芯片软件函数与变量内存布局优化精控方法

    函数和变量指定section放置方法与操作流程,兼具过程记录与详细说明,旨在打造一份实用的参考指南,助力开发者精准掌控程序的内存分布与执行逻辑。文档涵盖从默认section表的介绍,到多种放置手段的阐释,以及实际配置示例的展示
    的头像 发表于 04-30 16:38 589次阅读
    基于 IAR Embedded Workbench 的自研 MCU 芯片软件<b class='flag-5'>函数</b>与变量<b class='flag-5'>内存</b>布局优化精控方法

    函数指针的六个常见应用场景

    函数指针在嵌入式开发中有着广泛的应用,它让代码更加灵活,减少冗余,提高可扩展性。很多时候,我们需要根据不同的情况动态调用不同的函数,而函数指针正是实现这一需求的重要工具。本文将介绍六个
    的头像 发表于 04-07 11:58 1130次阅读
    <b class='flag-5'>函数</b>指针的六个常见应用场景

    详解RTOS中的Hook函数

    Hook函数是RTOS中的一个关键特性,通过该函数,用户可以增强对任务管理的控制,定义系统行为。
    的头像 发表于 03-24 16:14 839次阅读

    解锁TSMaster fifo函数:报文读取的高效方法

    前言:TSMaster目前有两种读取报文的模式:回调函数模式和fifo模式。fifo函数是TSMaster近期新增的函数,本文将重点介绍fifo模块。关于回调函数的使用方法可以参考帮助
    的头像 发表于 03-14 20:04 943次阅读
    解锁TSMaster fifo<b class='flag-5'>函数</b>:报文读取的高效方法

    C语言如何处理函数的返回值

    当你在函数的最后写上 return 0 的时候,它是如何返回给调用函数的? 比如 test 函数,为了待会更好的看懂汇编代码,我写成了 return 1234。 处理函数的返回值,是不
    的头像 发表于 01-16 09:21 749次阅读

    西门子TIA Portal中函数FC和函数块FB的相互转换

    描述 本文将介绍在西门子 TIA Portal 中使用 Add-In 插件实现函数 FC 和函数块 FB 的相互转换的方法和步骤。 第1步: 添加 PLC 设备。 选择西门子 CPU 1214C
    的头像 发表于 01-15 10:07 3038次阅读
    西门子TIA Portal中<b class='flag-5'>函数</b>FC和<b class='flag-5'>函数</b>块FB的相互转换

    不停的malloc程序会异常吗

    malloc 放在死循环里面,会是什么样的现象? 比如这样的代码,每次使用 malloc 申请 1M 大小的内存,其他什么操作也不做。 理论上来说,堆内存是有限的,如果不停的申请,
    的头像 发表于 01-14 09:17 843次阅读

    如何把两个数据返回给调用函数

    已经知道函数会返回两个数据,提前申请两个元素的内存,并且把数组作为参数传递过去,把返回值放在数组中就行。 第三种,定义一个全局的结构体变量,这样可以不用传参也不用返回,直接操作全局数据。 比较典型的错误写法有两种
    的头像 发表于 01-08 10:15 679次阅读

    关联接口函数与libmodbus移植

    可以发现,除了modbus.h包含的接口函数之外,modbus-rtu.h和modbus-tcp.h也包含了必要的接口函数
    的头像 发表于 12-30 15:20 1789次阅读
    关联接口<b class='flag-5'>函数</b>与libmodbus移植

    stdio.h实现了printf函数?

    我们平时包含的 stdio.h 头文件,里面是不是实现了 printf 函数? 为什么会有这个疑问?因为每次使用 printf,就得包含 stdio.h ,这就导致很多同学误以为,stdio.h
    的头像 发表于 12-18 10:28 869次阅读