#include<stdio.h>

/**
在C中动态分配内存的基本步骤有:
1,用malloc类的函数分配内存;
2,用这些内存支持应用程序
3,用free函数释放内存
二、动态内存分配函数
    malloc :从堆上分配内存
    realloc : 在之前分配的内存块的基础上,将内存重新分配为更大或者更小的部分
    calloc: 从堆上分配内存并清零
    free:将内存块返回堆
*/
void mainaa()
{
    int *pi = (int*) malloc(sizeof(int));
    *pi = 5;
    printf("*pi:%d\n",*pi);
    free(pi);
}
//为字符串分配内存,将其初始化,并逐个字符打印字符串,然而每次迭代name都会增加1,最后name会指向字符串结尾的NUL字符,
//分配内存的起始地址丢失了
void mainbb()
{
    //为10个双精度浮点数分配空间,需要80个字节
    //double *pd = (double*)malloc(NUMBER_OF_DOUBLES*sizeof(double));
    //以下程序只分配了10个字节
    const int NUMBER_OF_DOUBLES = 10;
    double *pd = (double*)malloc(NUMBER_OF_DOUBLES);

//初始化静态或全局变量时不能调用函数,下面的代码声明一个静态变量,并试图用
    //malloc来初始化,这样会产生一个编译时错误消息
    //static int *pi = malloc(sizeof(int));

char *name = (char*)malloc(strlen("Susan")+1);
    strcpy(name,"Susan");

while(*name != 0){
        printf("%c",*name);
        name++;
    }
}
/**
    使用calloc函数
    calloc会在分配的同时清空内存,该函数的原型如下:void *calloc(size_t numElements,size_t elementSize);
    calloc函数会根据numElements和elementSize两个参数的乘积来分配内存,并返回一个指向内存的第一个字节的指针。如果不能分配内存
    则返回null,此函数最初用来辅助分配数组内存。
    如果numElements或elementSize为0,那么calloc可能返回空指针。如果calloc无法分配内存就会返回空指针,而且全局变量errno会设置为ENOMEM(内存不足),
    这是POSIX错误码,有的系统上可能没有
**/
void maincc()
{
    //下面两端代码都是为pi分配了20字节,全部包含0
    //int *pi = calloc(5,sizeof(int));

//int *pi = malloc(5*sizeof(int));
    //memset(pi,0,5*sizeof(int));

/**
        memset函数会用某个值填充内存块,第一个参数是指向要填充的缓冲区的指针,第二个参数是填缓冲区的值,最后一个参数是要填充的字节数。
        如果内存需要清零可以使用calloc,不过执行calloc可能比执行malloc慢。cfree函数已经没用了。
    */
}
/**
    realloc函数
    realloc函数会重新分配内存,原型:void *realloc(void *ptr,size_t size);
    realloc函数返回指向内存块的指针。该函数接受两个参数,第一个参数是指向原内存块的指针,第二个是请求的大小。重新分配的块大小和第一个参数
    引用的块大小不同。返回值是指向重新分配的内存的指针。
    请求的大小可以比当前分配的字节数小或者大。如果比当前分配的小,那么多余的内存会还给堆,不能保证多余的内存会被清空。如果比当前分配的大,
    那么可能的话,就在紧挨着当前分配内存的区域分配新的内存,否则就会在堆的其他区域分配并把旧的内存复制到新区域。
    如果大小是0而指针非空,那么就释放内存。如果无法分配空间,那么原来的内存块就保持不变,不过返回的指针是空指针,且errno会设置为ENMOEM,
**/
void maindd()
{
    /**
        下例使用两个变量为字符串分配内存。一开始分配16个字节,但只用到了前面的13个字节(12个十六进制数字外加null结束字符(0))
    */
    char *string1;
    char *string2;
    string1 = (char*)malloc(16);
    strcpy(string1,"0123456789AB");
    
    /**
        紧接着,用realloc函数指定一个范围更小的内存区域。然后打印这两个变量的地址和内容
    */
    string2 = realloc(string1,8);
    printf("string1 value:%p [%s]\n",string1,string1);
    printf("string2 value:%p [%s]\n",string2,string2);
}
/**
    alloca函数和变长数组
    alloca函数(微软为malloca)在函数的栈帧上分配内存。函数返回后会自动释放内存。若低层的运行时系统不基于栈,
    allocal函数会很难实现,所以这个函数时不标准的,如果应用程序需要可移植就尽量避免使用它。
    C99引入了变长数组(VLA),允许函数内部声明和创建其长度由变量决定的数组,比如:
    void compute(int size){
        char * buffer[size];
        ...
    }
    这意味着内存分配在运行时完成,且将内存作为栈帧的一部分来分配。另外,如果数组用到sizeof操作符,也是在运行时而不是编译时执行。
    这么做只会有一点小小的运行时开销。而且一旦函数退出,立即释放内存。因为我们没有用malloc这类函数来创建数组,所以不应该用free函数来
    释放它。alloca函数也不应该返回指向数组所在内存的指针,但是可以解决。
    VLA的长度不能改变,一经分配其长度就固定了。
**/

/**
    动态内存分配技术
    1,资源获取即初始化
    资源获取即初始化(Resource Acquisition Is Initialization,RAII)是Bjarne Stroustrup发明的技术,可以用来解决C++中资源的分配和释放。
    即使有异常发生,这种技术也能保证资源的初始化和后续的释放。分配的资源最终总是会得到释放。
    有好几种方法可以在C中使用RAII。GNU编译器提供了非标准的扩展来支持这个特性,通过演示如何在一个函数中分配内存然后释放可以说明这种
    扩展。一旦变量超出作用域会自动触发释放过程。
    GNU的扩展需要用到RAII_VARIABLE宏,它声明一个变量,然后给变量关联如下属性
        1,一个类型。
        2,创建变量时执行的函数。
        3,变量超出作用域时执行的函数。
    这个宏如下所示:
        #define RAII_VARIABLE(vartype,varname,initval,dtor)\
            void _dtor_ ## varname (vartype * v){dtor(*v);}\
            vartype varname __attribute__((cleanup(_dtor_ ## varname))) = (initval)
    在下例中,我们将name变量声明为字符指针。创建它时会执行malloc函数,为其分配32字节。当函数结束时,name超出作用域就会执行free函数:
    void raiiExample(){
        RAII_VARIABLE(char*,name,(char*)malloc(32),free);
        strcpy(name,"RAII Example");
        printf("%s\n",name);
    }
    函数执行后会打印"RAII_Example"字符串。不用GNU扩展也可以达到类似效果。
    2、使用异常处理函数
    另外一种处理内存释放的方法是利用异常处理。尽管异常处理不属于标准C,但如果可以使用它且不考虑移植问题,它会很有用。下面说明利用
    Microsoft Visua Studio版的C语言的方法。
    这里的try块包含任何可能在运行时抛出异常的语句。不管有没有异常抛出,都会执行finally块,因此也一定会执行free函数。
    void exceptionExample(){
        int *pi = NULL;
        __try{
            pi = (int*)malloc(sizeof(int));
            *pi = 5;
            printf("%d\n",*pi);
        }
        __finally{
            free(pi);
        }
    }
*/

c语言动态分配内存及内存分配部分函数相关推荐

  1. C语言 :学习动态内存分配

    文章目录 C语言动态分配 为什么存在内存分配? 动态内存函数的介绍 `malloc` `free` `free`函数的**作用原理**是: 使用后将指针赋为`NULL` `calloc` 运用一次`c ...

  2. c语言链表动态分配内存,链表的C语言实现(含动态内存分配)

    转自:http://blog.csdn.net/21aspnet/article/details/146968 链表的C语言实现(含动态内存分配) 上 链表的C语言实现之动态内存分配 一.为什么用动态 ...

  3. c语言 malloc_C语言快速入门——动态内存分配

    在前面一系列的字符串操作中,我们都是先定义一个固定大小的字符数组,然后根据所需,或拷贝.或连接.或格式化来为这个数组提供内容.固定大小的数组意味着在程序运行期间,数组所占用的内存是确定的(即划分了固定 ...

  4. c语言链表内存分配失败,链表的C语言实现之动态内存分配

    链表的C语言实现之动态内存分配 來源:互聯網  2008-06-01 02:05:07  評論 一.为什么用动态内存分配 但我们未学习链表的时候,假如要存储数量比较多的同类型或同结构的数据的时候,总是 ...

  5. 内存的静态分配和动态分配的区别【转】 静态分配内存与动态分配内存的区别

    内存的静态分配和动态分配的区别[转] 来源: <http://blog.csdn.net/liuchao1986105/article/details/6724392> 内存的静态分配和动 ...

  6. 21.C 语言与 C++在内存分配有什么区别?

    C 语言与 C++在内存分配有什么区别? 在C语言中通过malloc和free来分配.释放内存空间:在C++语言中通过new和delete来分配和释放内存空间. malloc/free和new/del ...

  7. 内存的静态分配和动态分配的区别【转】

    来源: <http://blog.csdn.net/liuchao1986105/article/details/6724392> 内存的静态分配和动态分配的区别主要是两个: 一是时间不同 ...

  8. C语言学习笔记---动态内存分配

      数组在内存中时存储在连续的位置上,当声明一个数组的时候,编译器就会在内存中分配它所需要的空间,但是有时候还需要使用动态内存为数组分配空间.   比如现在要同统计一个班级学生的成绩,可以申请一个固定 ...

  9. 内存的静态分配和动态分配的区别

    内存的静态分配和动态分配的区别主要是两个: 一是时间不同.静态分配发生在程序编译和连接的时候.动态分配则发生在程序调入和执行的时候. 二是空间不同.堆都是动态分配的,没有静态分配的堆.栈有2种分配方式 ...

最新文章

  1. 【牛腩新闻发布系统】系统发布06
  2. pytorch中调整学习率的lr_scheduler机制
  3. 普诺飞思获创新工场新一轮投资,加速神经拟态视觉传感技术商业化
  4. 南邮 Android 课程设计,南邮大四课程设计.doc
  5. 编写简单的UDP应用
  6. 关于SAP CRM中间件系统搭建中遇到的一些问题
  7. springMVC3学习(十一)--文件上传CommonsMultipartFile
  8. python dict保存到文件_将dict写入txt文件并将其读回?
  9. git提取和拉取区别_每天一Git之起步 - 关于版本控制
  10. ps练习实例_拥有一份史上最全面的50集ps抠图学习教程是什么一种体验?
  11. jquery ajax实例 php,jquery中各个ajax实例操作
  12. SparkSQL概念介绍
  13. java 字符串索引从0开始_Java程序从指定的索引中搜索子字符串
  14. 5G如何改变社会?中国移动出了一本书来解读
  15. 对i++,i--,++i,--i深刻认识以及printf()函数打印的过程
  16. 提前祝福你和你和家人国庆节快乐,旅途愉快!
  17. super 和 this
  18. unity动画转换插件 AnimationConverter, humanoid generic legacy
  19. python输入年份输出年历_python打印万年历
  20. SDUT 王小二切饼

热门文章

  1. 2 Arduino基本数字输出功能LED灯
  2. Thomas Zhang的杂货铺
  3. 跻身多链时代,一文读懂区块链「桥」及其设计权衡
  4. XSS注入(dvwa)
  5. 天翼物联助力杭州电信打造全国首个5G LAN全连接工厂
  6. 验证码是自动化的天敌?看看大神是怎么解决的
  7. opencv调试-内存泄露
  8. 技术分享|三相并网逆变器PQ控制算法控制解析
  9. 微机原理-80386(3)
  10. Redefinition of enumerator ios