原文地址:http://www.cnblogs.com/3me-linux/p/3962152.html

calloc(), malloc(), realloc(), free(),alloca()

内存区域可以分为栈、堆、静态存储区和常量存储区,局部变量,函数形参,临时变量都是在栈上获得内存的,它们获取的方式都是由编译器自动执行的。
利用指针,我们可以像汇编语言一样处理内存地址,C 标准函数库提供了许多函数来实现对堆上内存管理,其中包括:malloc函数,free函数,calloc函数和realloc函数。使用这些函数需要包含头文件stdlib.h。

四个函数之间的有区别,也有联系,我们应该学会把握这种关系,从而编出精炼而高效的程序。

在说明它们具体含义之前,先简单从字面上加以认识,前3个函数有个共同的特点,就是都带有字符”alloc”,就是”allocate”,”分配”的意思,也就是给对象分配足够的内存,” calloc()”是”分配内存给多个对象”,” malloc()”是”分配内存给一个对象”,”realloc()”是”重新分配内存”之意。”free()”就比较简单了,”释放”的意思,就是把之前所分配的内存空间给释放出来。

void *calloc(size_t nobj, size_t size);

分配足够的内存给nobj个大小为size的对象组成的数组, 并返回指向所分配区域的第一个字节的指针;
若内存不够,则返回NULL. 该空间的初始化大小为0字节.
char *p = (char *) calloc(100,sizeof(char));

void *malloc(size_t size);

分配足够的内存给大小为size的对象, 并返回指向所分配区域的第一个字节的指针;
若内存不够,则返回NULL. 不对分配的空间进行初始化.
char *p = (char *)malloc(sizeof(char));

void *realloc(void *p, size_t size);

将p所指向的对象的大小改为size个字节.
如果新分配的内存比原内存大, 那么原内存的内容保持不变, 增加的空间不进行初始化.
如果新分配的内存比原内存小, 那么新内存保持原内存的内容, 增加的空间不进行初始化.
返回指向新分配空间的指针; 若内存不够,则返回NULL, 原p指向的内存区不变.
char *p = (char *)malloc(sizeof(char));
p= (char *)realloc(p, 256);

void free(void *p);

释放p所指向的内存空间; 当p为NULL时, 不起作用.
p必先调用calloc, malloc或realloc.

值得注意的有以下5点:

(1)通过malloc函数得到的堆内存必须使用memset函数来初始化

malloc函数分配得到的内存空间是未初始化的。因此,一般在使用该内存空间时,要调用另一个函数memset来将其初始化为全0,memset函数的声明如下:void * memset (void * p,int c,int n) ;

该函数可以将指定的内存空间按字节单位置为指定的字符c,其中,p为要清零的内存空间的首地址,c为要设定的值,n为被操作的内存空间的字节长度。如果要用memset清0,变量c实参要为0。

malloc函数和memset函数的操作语句一般如下:

int * p=NULL;

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

if(p==NULL)

printf(“Can’t get memory!\n”);

memset(p,0,siezeof(int));

(2)使用malloc函数分配的堆空间在程序结束之前必须释放

从堆上获得的内存空间在程序结束以后,系统不会将其自动释放,需要程序员来自己管理。一个程序结束时,必须保证所有从堆上获得的内存空间已被安全释放,否则,会导致内存泄露。

我们可以使用free()函数来释放内存空间,但是,free函数只是释放指针指向的内容,而该指针仍然指向原来指向的地方,此时,指针为野指针,如果此时操作该指针会导致不可预期的错误。安全做法是:在使用free函数释放指针指向的空间之后,将指针的值置为NULL。

(3)calloc函数的分配的内存也需要自行释放

calloc函数的功能与malloc函数的功能相似,都是从堆分配内存,它与malloc函数的一个显著不同时是,calloc函数得到的内存空间是经过初始化的,其内容全为0。calloc函数适合为数组申请空间,可以将size设置为数组元素的空间长度,将n设置为数组的容量。

(4)如果要使用realloc函数分配的内存,必须使用memset函数对其内存初始化

realloc函数的功能比malloc函数和calloc函数的功能更为丰富,可以实现内存分配和内存释放的功能。realloc 可以对给定的指针所指的空间进行扩大或者缩小,无论是扩张或是缩小,原有内存的中内容将保持不变。当然,对于缩小,则被缩小的那一部分的内容会丢失。realloc 并不保证调整后的内存空间和原来的内存空间保持同一内存地址。相反,realloc 返回的指针很可能指向一个新的地址。

所以,在代码中,我们必须将realloc返回的值,重新赋值给 p :

p = (int *) realloc(p, sizeof(int) *15);

甚至,你可以传一个空指针(0)给 realloc ,则此时realloc 作用完全相当于malloc。

int* p = (int *)realloc (0,sizeof(int) * 10); //分配一个全新的内存空间,

这一行,作用完全等同于:

int* p = (int *)malloc(sizeof(int) * 10);

(5)关于alloca()函数

还有一个函数也值得一提,这就是alloca()。其调用序列与malloc相同,但是它是在当前函数的栈帧上分配存储空间,而不是在堆中。其优点是:当 函数返回时,自动释放它所使用的栈帧,所以不必再为释放空间而费心。其缺点是:某些系统在函数已被调用后不能增加栈帧长度,于是也就不能支持alloca 函数。尽管如此,很多软件包还是使用alloca函数,也有很多系统支持它。

总结:应用时候需要记得,只有calloc可以指定个数和大小,而且能够对分配内存进行初始化,其余函数均不会对内存进行初始化工作,需要自行调用memset()函数.

C:malloc/calloc/realloc/alloca内存分配函数的更多相关文章

  1. malloc/calloc/realloc/alloca内存分配函数

    calloc(), malloc(), realloc(), free(),alloca() 内存区域可以分为栈.堆.静态存储区和常量存储区,局部变量,函数形参,临时变量都是在栈上获得内存的,它们获取 ...

  2. C语言 malloc calloc realloc alloc 在分配内存时的 区别

    malloc : 向堆申请分配内存,不初始化 calloc  : 向堆申请分配内存,初始化为0 realloc:  向堆申请分配内存,可调整大小 alloc   :   向栈申请内存,不需手动释放

  3. 【转】【C/C++】内存分配函数:malloc,calloc,realloc,_alloca

    转自:http://www.cnblogs.com/particle/archive/2012/09/01/2667034.html#commentform malloc: 原型:extern voi ...

  4. 内存分配函数malloc、realloc、calloc、_alloca

    1.内存分配函数_alloca.malloc.realloc.calloc: _alloca 函数原型void * __cdecl _alloca(size_t); 头文件:malloc.h _all ...

  5. C语言内存分配函数malloc——————【Badboy】

    C语言中经常使用的内存分配函数有malloc.calloc和realloc等三个,当中.最经常使用的肯定是malloc,这里简单说一下这三者的差别和联系. 1.声明 这三个函数都在stdlib.h库文 ...

  6. C标准库-数值字符串转换与内存分配函数

    原文链接:http://www.orlion.ga/977/ 一.数值字符串转换函数 #include <stdlib.h> int atoi(const char *nptr); dou ...

  7. malloc calloc realloc,new区别联系以及什么时候用

    三个函数的申明分别是:void* realloc(void* ptr, unsigned newsize);void* malloc(unsigned size);void* calloc(size_ ...

  8. C语言之内存分配函数

    #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { /********* ...

  9. malloc,calloc,realloc三者的区别

    malloc,calloc,realloc三者都可以运用与动态分配数组. malloc:用malloc必须要自己初始化,可以用memset(arr,0,cnt*sizeof(int)) calloc: ...

随机推荐

  1. nginx 深入篇

    nginx 防盗链 上文介绍了如何以最最简单的方式配置静态资源,还存在一定的隐患,一般的盗链如何预防, 设置验证referer server { listen 8000; server_name 12 ...

  2. Linux下将使用rm删除的文件显示在回收站中

    人难免会失误,出现一些问题,在删除文件的时候使用rm,删除之后就后悔了.因为rm命令删除的文件是不进入回收站的,这使得恢复起来很困难.解决这一难题,可以使用python编写的trash-cli( ht ...

  3. 愚人节CDACMFinal

    这个啊,愚人节的ACM之赛,其实还是很有意思的.之前因为星期天不能休息还怨声载道,但真的打起来了就是觉得特别有意思. 我们队,最开始乱搞电脑,cmd都没有办法调用了,霎时间十分慌张(而且我过于慌张忘了 ...

  4. SQL 运算符

    运算符是一个保留字或字符,主要用于连接WHERE后面的条件. 一.算数运算符 运算符 描述 + 加法 把运算符两边的值相加 - 减法 左操作数减去右操作数 * 乘法 把运算符两边的值相乘 / 除法 左 ...

  5. laravel 模型事件 updated 触发条件

    1. 只有 $sku->{attribute} != $sku->getOriginal({attribute}) 不一致的时候才会触发 getDirty() 不为空的时候才触发, 而且不 ...

  6. 选择监听事件ItemListener(是否被选择)

    [界面说明] 下拉列表框,选谁谁显示.复选框与单选按钮,输出被选与否的状态.知识点主要代码为: int state = e.getStateChange(); ItemEvent.SELECTED I ...

  7. JVM总结(二):垃圾回收器

    这一节我们来总结一下JVM垃圾收集器方面的东西. 垃圾回收器 判断对象引用是否失效 对象生存判断算法 引用判断过程 垃圾收集算法简介 垃圾收集器 新生代垃圾收集器 老年代垃圾收集器 新生代和老年代垃圾 ...

  8. Redis和Memcached对比【转】

    Redis和Memcached对比 这两年 Redis火得可以,Redis也常常被当作 Memcached的挑战者被提到桌面上来.关于Redis与Memcached的比较更是比比皆是.然而,Redis ...

  9. authentication failed for xxx错误

    现象: 公司windows定期修改过密码后 一直报错.push的时候显示“Authentication Failed for http://x.x.x.x/x/git” 猜想: 发现可能是账号问题. ...

  10. indexOf与includes的比较

    indexOf和includes都代表检测数组或字符串中是否包含某一个元素 其中indexOf返回的是数值类型,而includes返回的是布尔类型 var ary = [,,]; console.lo ...