• C语言-第29课


    第29课 - 动态内存分配

     

    先看一段例程,超市模拟程序,记录卖出去东西的价格以及名称

    #include <stdio.h>

    #include <string.h>

    struct Product

    {

        char name[128];

        int price;

    };

    struct Product pro[1000];

    struct Product sale;

    void waitForSale()

    {

        printf("Record Product: ");

        scanf("%s %d", sale.name, &sale.price);

    }

    int main()

    {

        int i = 0;    

        for(i=0; i<1000; i++)

        {

            waitForSale();

            strcpy(pro[i].name, sale.name);

            pro[i].price = sale.price;  

            printf("%s, %d ", pro[i].name, pro[i].price);

        }

        return 0;

    }

    这里面最大的问题就是,我们设定物品最大的数量就是1000,但是物品超过1000的时候,就会使程序出现问题。这时,我们就可以使用动态内存分配了。

     

    1. 为什么使用动态内存分配?

    (1) C语言中的一切操作都是基于内存的。

    (2) 变量和数组都是内存而定别名,如何分配这些内存由编译器在编译期间决定

    (3) 定义数组的时候必须指定数组的长度,而数组的长度是在编译期就必须决定的。我们面的需求是,程序运行的过程中,可能需要使用一些额外的内存空间。

     

    针对例程的问题,我们有两种解决方法:

    (1)定义1000个数组,当超过1000的时候,我们定义指针重新申请

    (2)直接定义指针,不需要数组了。我们直接用指针指向malloc1000),当超过的时候,重新指。

    无论哪种方法都需要动态内存分配。

     

    1. mallocfree

    1mallocfree用于执行动态内存分配和释放

     

    (3)malloc分配的是一块连续的内存,以字节为单位,而且不带任何的类型信息

    (4)free用于将动态内存归还系统

    void* malloc(size_t size)

    void free(void* pointer)

    系统里面有一个区域,这个区域有一些闲置的内存,它的作用就是完成动态内存的申请和归还的。

    注意:malloc实际分配的内可能会比请求的稍微多一些,但是不能依赖于编译器的这个行为

    当请求的动态内存无法满足malloc返回NULL

    free的参数为NULL时,函数直接返回

     

     

    1. calloc函数:需要用到的头文件stdlib.h 
      void *colloc(size_t num_elements,size_t element_size); 
      功能:功能同malloc是一样的,但是作初始化 
      参数:num_elements是所需的元素的数量,element_size是每个元素的字节数 
      返回:malloc函数一样 
      也是需要与free(p)进行对称使用

    #include<stdio.h> 

    #include<stdlib.h>

    int main(void)

    {

    printf("please input one number:");

    int n;

    scanf("%d",&n);

    int *p = (int *)calloc(n,sizeof(int));

    if(p!=NULL)

    {

    int i;

    for(i=0;i<n;i++)

    {

    printf("%d ",*(p+i)); }

    printf(" "); free(p); }

    else

    {

    printf("calloc error ");

     }

    return 0;

    }

     

    1. realloc函数:需要用到的头文件(stdlib.h),动态扩大缩小申请的内存 
      void *realloc(void *ptr,size_t new_size); 
      功能:在指针ptr指向的内存基础上扩大或者缩小内存 
      参数:ptr是指向先前通过malloc,callocrealloc函数后分配的内存块的指针,new_size是内存块的新尺寸,可能大于或者小于原有内存尺寸;这个是追加到new_size的新的内存 
      reallocC语言中也被称为动态数组; 
      realloc函数使用的注意点
      1当扩展内存的时候,不会对添加进内存块的字节进行初始化 
      2若不能调整内存则返回NULL,但原有内存中的数据是不会发生改变的 
      3若第一个参数为NULL那么功能 等同与malloc函数,若第二个参数为0,那么会释放调用内存块

    realloc(NULL,10*size(int)) 等同malloc(10*sizeof(int));

    realloc(p,0); 等同于free

    例程分析:

    #include <stdio.h>

    #include <malloc.h>

    int main()

    {

        int i = 0;

        int* pI = (int*)malloc(5 * sizeof(int)); //申请了20个空间

        short* pS = (short*)calloc(5, sizeof(short)); //申请了10个空间

        for(i=0; i<5; i++)

        {

            printf("pI[%d] = %d, pS[%d] = %d ", i, pI[i], i, pS[i]);

        }

         pI = (int*)realloc(pI, 10 * sizeof(int));   //重新分配

        for(i=0; i<10; i++)

        {

            printf("pI[%d] = %d ", i, pI[i]);

        }  

        free(pI);

    free(pS);

     return 0;

    }

    运行结果:

    pI[0] = -842159451, pS[0] =0

    pI[1] = -842159451, pS[1] =0

    pI[2] = -842159451, pS[2] =0

    pI[3] = -842159451, pS[3] =0

    pI[4] = -842159451, pS[4] =0

    pI[0] = -842159451

    pI[1] = -842159451

    pI[2] = -842159451

    pI[3] = -842159451

    pI[4] = -842159451

    pI[5] = -842159451

    pI[6] = -842159451

    pI[7] = -842159451

    pI[8] = -842159451

    pI[9] = -842159451

     

     

    小结:

    动态内存分配是C语言中强大功能。

    l 程序能够在需要的时候有机会试用更多的内存。

    l malloc单纯的从系统中申请固定字节大小的内存。

    l calloc能以类型大小为单位申请内存并且初始化。

    l realloc用于重置内存大小。

     

     

     

     

     

    1. 常见的内存错误:

    1段错误 :
    使用未分配成功的内存 
    避免方式:在使用内存之前检查指针是否为NULL 
    引用分配成功但尚未初始化的内存 
    避免方式:赋予初值,即便是赋予零值也不可省略 
    内存分配成功并且已经初始化,但操作越过了内存的边界 
    避免:注意下表的使用不能超出边界 
    忘记释放内存,造成内存泄露 
    避免方式:申请内存的方式和释放内存的方式需要成双成对 
    释放内存之后却继续去使用这一块内存 
    避免方式:使用free内存之后,把指针置为NULL

    2内存错误的注意点: 
    指针消亡了,并不表示它所指向的内存会被自动释放,(free之前,直接将指针设为NULL) 
    内存释放了,并不代表指针会消亡或者成了NULL指针;(free之后,指针并没有进行NULL设置)

    3野指针: 
    野指针的形成是指针变量没有被初始化,任何指针变量刚被创建的时候不会自动成为NULL指针,它的缺省值是最忌的,它会乱指一气

    指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法内存

    free内存块之后,需要将指针设置为NULL,如果没有设置为NULL,也会出现野指针,它是指向垃圾内存的指针;

    多次free内存块,是会导致程序崩溃的

     

  • 相关阅读:
    互联网搜索引擎——文本预处理
    nltk的pos_tag
    nltk.stem 词干提取(stemming)
    python3的encode和decode涉及的str和bytes转换
    power rails 'GND' and 'VCC/VDD' are interconnected in net VCC
    impot不能导入自己写的python文件【爆红】
    No module named 'tensorflow.contrib'
    解决spark-submit的There is insufficient memory for the Java Runtime Environment to continue.(老顽固问题) failed; error='Cannot allocate memory' (errno=12)
    spark的standalone模式下:查看任务结束后的历史记录
    只是为了保存一些有用链接而已
  • 原文地址:https://www.cnblogs.com/free-1122/p/9783862.html
Copyright © 2020-2023  润新知