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

    浏览量

    38805
  • 大数据
    +关注

    关注

    64

    文章

    9096

    浏览量

    144060
  • malloc
    +关注

    关注

    0

    文章

    53

    浏览量

    391

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

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

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

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Linux内核伙伴系统内存申请函数详解:从原理到实战

    次分配粒度" 巧妙解决了外碎片问题,而我们申请内核内存的所有操作,最终都要通过伙伴系统提供的核心函数来完成。
    的头像 发表于 02-10 16:58 3729次阅读
    Linux内核伙伴系统<b class='flag-5'>内存</b>申请<b class='flag-5'>函数</b>详解:从原理到实战

    keil中c语言的动态分配内存

    动态内存分配我们可以自由更改分配的空间,使其“可大可小”。 1.常用的动态内存分配函数(都包含在头文件中)(1)malloc和freemalloc是最常用到的
    发表于 01-21 06:04

    嵌入式开发常用函数速查表

    在嵌入式开发中,掌握常用函数的用法可以大大提高开发效率。无论是单片机初学者还是有一定经验的工程师,熟悉函数库和调用方式都是必备技能。今天,我们为大家整理一份嵌入式开发常用函数速查表,覆盖GPIO
    的头像 发表于 01-19 09:06 467次阅读
    嵌入式开发常用<b class='flag-5'>函数</b>速查表

    matlab调用dll动态函数,死机问题,如何强行跳出?

    matlab调用dll动态库中的函数,例如图莫斯,发送数据时,经常会卡死,是否有办法限制时间,比如3秒,没有回应,就强行结束函数调用。执行后续逻辑。
    发表于 12-31 10:14

    内存拷贝函数 memcpy原理及实现

    内存拷贝函数memcpymemcpy是memory copy的缩写,意为内存复制,在写C语言程序的时候,我们常常会用到它。它的函原型如下:void *memcpy(void *dest, const
    发表于 12-26 08:03

    嵌入式系统中,动态分配内存可能发生的问题是什么?

    尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。 那么嵌入式系统中,动态分配内存可能发生的问题是什么? 这 里,我期望应试者能提到
    发表于 12-22 09:42

    三种类型内存的使用

    的,因为底层数据会被默默删除。自动存储通常被称为“栈”。 分配的存储:运行malloc() 会返回的内存类型,这种内存会一直保留,直到被 free() 函数释放,所以可以被传递到任
    发表于 12-12 06:43

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

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

    使用函数块实现三相电机正反转控制

    在使用西门子S1200PLC,所使用的软件是博途软件,在这个软件里运用了块的概念。比如我们常见的组织块(OB)、函数块(FB)、数据块(DB)以及函数FC等。今天我们来具体交流一下这个函数块(FB)的具体使用方法。
    的头像 发表于 10-15 14:40 2920次阅读
    使用<b class='flag-5'>函数</b>块实现三相电机正反转控制

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

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

    为什么立功要做汽车总线ZXDoc软件?

    近年来,国内汽车产业快速迈向智能化和网联化,“软件定义汽车”既成共识,立功汽车软件ZXDoc的出现看似偶然,实则必然。ZLG致远电子:技术积淀与战略布局的必然成果公司从2010年启动汽车总线
    的头像 发表于 09-22 11:34 1417次阅读
    为什么<b class='flag-5'>周</b><b class='flag-5'>立功</b>要做汽车总线ZXDoc软件?

    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 2229次阅读

    C语言中的内联函数与宏

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

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

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