zoukankan      html  css  js  c++  java
  • C语言动态内存管理


    在C语言中,编写程序的时候不能确定内存的大小,希望程序在运行的过程中根据数据量的大小动态的分配内存。动态内存管理,就是指在程序运行过程中动态的申请和释放内存空间。

    C语言允许程序动态管理内存,需要时随时开辟,不需要时随时释放。内存的动态管理是通过调用库函数来实现的,主要有malloc和free函数。

    一、相关的库函数

    1、malloc 函数

    函数的原型:

    void *malloc(unsigned int size);
    

    malloc的作用是向系统申请一块大小为size的连续内存空间,如果申请失败,函数返回0,如果申请成功,返回成功分配内存块的起始地址。

    例如:

    malloc(100); // 申请 100 个字节的临时分配域,返回值为其第一个字节的地址
    

    malloc的返回值的地址的基类型为void,即不指向任何类型的数据,只提供一个地址,程序中需要定义一个指针来指向动态分配的内存地址。

    例如:

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

    2、free 函数

    函数的原型:

    void free(void *p);
    

    free的作用是释放指针p指向的动态内存空间,p是调用malloc函数时返回的地址,free函数无返回值。

    例如:

    free(pi);     // 释放指针变量pi指向的已分配的动态空间
    

    示例(book107.c)

    /*
     * 程序名:book107.c,此程序用于演示C程序动态内存管理。
     * 作者:C语言技术网(www.freecplus.net) 日期:20190525
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct st_girl  // 超女结构体
    {
      char name[50];     // 姓名
      int  age;          // 年龄
    };
    
    int main(int argc,char *argv[])
    {
      int    *pi=malloc(sizeof(int));    // 分配int类型大小的内存
      long   *pl=malloc(sizeof(long));   // 分配long类型大小的内存
      double *pd=malloc(sizeof(double)); // 分配double类型大小的内存
      char   *pc=malloc(101);            // 分配101字节的内存,可存放100个字符的字符串
      struct st_girl *pst=malloc(sizeof(struct st_girl)); // 分配struct st_girl结构体大小的内存
    
      // 以下代码是像普通指针和变量一样使用动态分配的内存
      *pi=10;     printf("*pi=%d
    ",*pi);
      *pl=20;     printf("*pl=%d
    ",*pl);
      *pd=10.5;   printf("*pd=%.1f
    ",*pd);
      strcpy(pc,"西施"); printf("*pc=%s
    ",pc);
      strcpy(pst->name,"杨玉环"); pst->age=21;
      printf("name=%s,age=%d
    ",pst->name,pst->age);
      
      // 释放动态分配的内存
      free(pi); free(pl); free(pd); free(pc); free(pst);
    }
    

    运行效果

    在这里插入图片描述

    二、内存被耗尽

    使用动态分配内存技术的时候,分配出来的内存必须及时释放,否则会引起系统内存耗尽,这话说起来简单,好像很容易做到,但是在实际开发中,程序员往往是漏洞百出。

    内存问题是C程序员的主要问题之一,是初学者的恶梦。

    三、野指针

    野指针就是无效的指针,与空指针不同,野指针无法通过简单地判断是否为 NULL避免,而只能通过养成良好的编程习惯来尽力减少。

    1、指针变量未初始化

    指针变量刚被创建时不一定会自动初始化成为空指针(与编译器有关),它的缺省值是可能随机的,它会随便乱指。所以,指针变量在创建的同时应当被初始化,要么将指针的值设置为0,要么让它指向合法的内存。

    int *pi=0;
    

    int i;
    int *pi=&i;
    

    2、指针释放后之后未置空

    指针在free时会把指针所指的内存给释放掉,但指针不一定会赋值0(也与编译器有关),如果对释放后的指针进行操作,相当于非法操作内存。释放内存后应立即将指针置为0。

    free(pi);
    pi=0;
    

    四、应用经验

    1、数组申明的改进

    在C语言的早期标准中,定义数组必须用常量指明大小,不能用变量。

    char str[101];        // 可以这样
    int len=101;
    char str[len];         // 不可以这样
    

    程序在运行的时候,如果要定义一个字符串存放100个字符,那怎么办,只能通过动态分配内存技术。

    char *str=malloc(101);
    

    现在,定义数组可以用变量指明大小,就不必为数组动态分配内存了。

    还有,C++的string是一个变长的字符串,非常好用,程序员根本不必关心内存的问题。

    2、链表

    链表是C语言的一个经典的数据结构,相当于一个动态的结构体数组,非常巧妙,功能强大,但操作也麻烦,在这里我就不介绍了。

    在C++中,容器全完代替了链表的功能,极其好用,程序员也不必关心内存的问题。

    3、我的建议

    在中国,没有纯C程序员,如果他不会C++,不是他对C有多么执着,可能是不会C++。

    至少十年了,我不再使用动态内存分配技术,也想不到有什么场景非得用动态内存分配技术。

    哦,嵌入式开发可能是个例外,可能还有其它只能用C不能用C++的场景。

    动态内存分配并不是什么高大上的技术,我是一个实用的程序员,绝不给自己挖坑,这与水平高低无关。

    五、课后作业

    编写示例程序,把本章节介绍的知识点全部演示一遍,用程序演示可以加深您的理解和映象。

    六、版权声明

    C语言技术网原创文章,转载请说明文章的来源、作者和原文的链接。
    来源:C语言技术网(www.freecplus.net)
    作者:码农有道

    如果文章有错别字,或者内容有错误,或其他的建议和意见,请您留言指正,非常感谢!!!

  • 相关阅读:
    atitit.nfc 身份证 银行卡 芯片卡 解决方案 attilax总结
    atitit.php 流行框架 前三甲为:Laravel、Phalcon、Symfony2 attilax 总结
    Atitit.执行cmd 命令行 php
    Atitit. 图像处理jpg图片的压缩 清理垃圾图片 java版本
    atitit。企业组织与软件工程的策略 战略 趋势 原则 attilax 大总结
    atitit. 管理哲学 大毁灭 如何防止企业的自我毁灭
    Atitit.java的浏览器插件技术 Applet japplet attilax总结
    Atitit.jquery 版本新特性attilax总结
    Atitit. 软件开发中的管理哲学一个伟大的事业必然是过程导向为主 过程导向 vs 结果导向
    (转)获取手机的IMEI号
  • 原文地址:https://www.cnblogs.com/wucongzhou/p/12498768.html
Copyright © 2011-2022 走看看