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

电子说

1.3w人已加入

描述

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

第一章为程序设计基础,本文为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。

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

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分