• C语言动态内存管理和动态内存分配

    动态内存管理

    在编写程序时,通常并不知道需要处理的数据量,或者难以评估所需处理数据量的变动程度。在这种情况下,要达到有效的资源利用,必须在运行时动态地分配所需内存,并在使用完毕后尽早释放不需要的内存,这就是动态内存管理原理。

    动态内存管理同时还具有一个优点:当程序在具有更多内存的系统上需要处理更多数据时,不需要重写程序。标准库提供以下四个函数用于动态内存管理:

    (1) malloc()、calloc()
    分配新的内存区域。

    (2) realloc()
    调整已分配的内存区域。

    (3) free()
    释放已分配的内存区域。

    上述所有函数都声明在头文件 stdlib.h 中。对象在内存中所占空间的大小是以字节数量为单位计算的。许多头文件(包括 stdlib.h)专门定义了类型 size_t 用来保存这种内存空间的相关信息。例如,sizeof 运算符以类型 size_t 返回字节数量。

    动态内存分配

    两个内存分配函数 malloc()和 calloc()的参数不一样

    void*malloc(size_t size);

    函数 malloc()分配连续的内存区域,其大小不小于 size。当程序通过 malloc()获得内存区域时,内存中的内容尚未决定。

    void*calloc(size_t count,size_t size);

    函数 calloc()分配一块内存区域,其大小至少是 count_size。换句话说,上述语句分配的空间应足够容纳一个具有 count 个元素的数组,每个元素占用 size 个字节。而且,calloc()会把内存中每个字节都初始化为 0。

    两个函数都返回 void 指针,这种指针被称为无类型指针(typeless pointer)。返回指针的值是所分配内存区域中第一个字节的地址,当分配内存失败时,返回空指针。

    当程序将这个 void 指针赋值给不同类型的指针变量时,编译器会隐式地进行相应的类型转换。然而,一些程序员倾向于使用显式类型转换。当获取所分配的内存位置时,所使用的指针类型决定了该如何翻译该位置的数据。

    下面是一些示例:

    #include <stdlib.h>                       // 提供函数原型
    typedef struct { long key;
                     /* ...其他成员... */
                   } Record;                // 一个结构类型
    float *myFunc( size_t n )
    {
       // 为一个double类型对象分配存储空间
       double *dPtr = malloc( sizeof(double) );
       if  ( dPtr == NULL )                 // 内存不足
       {
         /* ...处理错误... */
         return NULL;
       }
       else                                 // 获得内存:使用它
       {
         *dPtr = 0.07;
         /* ... */
       }
       // 为两个Record类型分配存储空间
       Record *rPtr;
       if  ( ( rPtr = malloc( 2 * sizeof(Record) ) == NULL )
       {
         /* ...处理内存不足错误... */
         return NULL;
       }
       // 为一个具有n个float元素的数组分配存储空间
       float *fPtr = malloc( n * sizeof(float) );
       if ( fPtr == NULL )
        {
         /* ...处理错误... */
         return NULL;
        }
        /* ... */
        return fPtr;
    }

    将所分配的内存区域中每个字节都初始化为 0,这种方式很有意义,它确保不只把分配给结构对象的内存都默认地初始化为 0,连成员之间的填补位置也是 0。

    在这种情况下,函数 calloc()比 malloc()更有优势,虽然在部分 C 语言实现版本中,它的运行效率不及后者。对于要分配的内存空间,函数calloc()的表示方式有所区别。可以把上述示例中的部分语句使用函数 calloc()重新编写:

    // 为一个double类型对象分配存储空间
    double *dPtr = calloc( 1, sizeof(double) );
    // 为两个Record类型分配存储空间
    Record *rPtr;
    if ( ( rPtr = calloc( 2, sizeof(Record) ) == NULL )
    { /* ...处理内存不足错误... */ }
    // 为一个具有n个float元素的数组分配存储空间
    float *fPtr = calloc( n, sizeof(float));

更多...

加载中...