欢迎光临
我们一直在努力

C语言-动态内存管理

程序员自己手动申请和释放堆区空间,更灵活。(以下函数使用时都必须包含头文件<stdlib.h>)

malloc函数

向内存堆区申请一块连续可用的内存空间,并返回这块内存空间的首地址,函数定义:void* malloc(size_t num);num的单位是:字节。

返回值:

  • 开辟成功,返回这块空间的首地址;
  • 开辟失败,返回NULL;(因此在每次调用完malloc函数后,要对返回只进行判断后才能使用这块空间)
  • 返回值是void*类型,具体使用时要进行强制类型转换
  • size = 0时,函数未定义,行为取决于编译器本身。

int main()
{
int* p = (int*)malloc(5 * sizeof(int));
if (p == NULL)
{
perror("malloc");
return 1;
}
int i = 0;
for (i = 0;i < 5;i++)
{
*(p + i) = i + 1;
}
free(p);
p = NULL;
return 0;
}

free函数

释放通过动态内存分配函数申请的内存空间,函数定义:void free(void* ptr);

  • ptr指向释放内存块指针;
  • ptr指向的内存空间不是动态开辟的,则函数为定义,不会有操作;
  • ptr为NULL,则什么都不做;
  • 在写代码时,一般释放完内存空间,要将该指针指向NULL.

calloc函数

在申请完连续空间后,将每一个字节置0,再返回这块空间的首地址;

函数声明:void* calloc(size_t num,size_t size);

  • num为申请个数;
  • size为申请的内存空间中每个的尺寸大小;(与前面的个数对应)
  • 其余用法以及返回值等均与malloc函数相同。

int main()
{
int* p = (int*)calloc(5 , sizeof(int));//创建5个整形变量的连续空间,并将其全部置0
if (p == NULL)//判断空间是否申请成功
{
perror("calloc");
return 1;
}
int i = 0;
for (i = 0;i < 5;i++)
{
*(p + i) = i + 1;
}
free(p);//释放空间
p = NULL;//释放后,p为野指针,让其指向NULL
return 0;
}

realloc函数

对已经开辟的动态内存空间的大小进行调整(扩大或者缩小)。

函数声明:void* realloc(void* ptr,size_t size);

  • ptr指向要调整的内存空间的起始地址,如果ptr指向NULL,则realloc函数和malloc函数的功能基本一致;
  • size是调整完之后内存空间的大小,单位是:字节;
  • 返回值:调整成功,返回调整后的内存空间的首地址(可能与原地址不同);调整失败,返回NULL,原内存空间保持不变。

realloc调整内存空间大小的两种情况

  • 原有内存空间后面有足够大的内存空间,要扩展的内存直接在原内存空间后面追加,原内存空间中数据不变,内存空间的起始地址不变;
  • 原有内存空间后面没有足够大的内存空间,会在内存的堆区寻找新的满足要求的内存空间,返回新的内存空间的起始地址;
    • 在堆区寻找新的满足要求的内存空间;
    • 将原内存空间的数据拷贝到新内存空间中;
    • 释放就内存空间,返回新内存空间的起始地址。

    #include<stdio.h>
    #include<stdlib.h>

    int main()
    {
    int* p = (int*)calloc(5 , sizeof(int));
    if (p == NULL)
    {
    perror("calloc");
    return 1;
    }
    int i = 0;
    for (i = 0;i < 5;i++)
    {
    *(p + i) = i + 1;
    }
    int* ptr = (int*)realloc(p, 10 * sizeof(int));
    //对动态内存空间进行扩展,20个字节扩展到40个字节
    if (ptr == NULL)
    {
    perror("realloc");
    return 2;
    }
    p = ptr;
    ptr = NULL;
    for (i = 5; i < 10; i++)
    {
    p[i] = i + 1;
    }
    free(p);
    p = NULL;
    return 0;
    }

    柔性数组

    结构体+动态内存管理

    结构体中最后一个成员,且未指定数组长度。

    柔性数组的特点

  • 结构体中柔性数组成员前面必须至少有一个其他成员;(保证结构体有内存空间)
  • sizeof()返回的结构体大小不包括柔性数组的内存;
  • 包含柔性数组的结构体内存用malloc()函数进行动态内存分配,并且分配的内存大小应该大于结构体的内存大小,以适应柔性数组预期大小。
  • 柔性数组的优点

  • 相较于传统写法进行动态内存分配的次数少,方便内存释放;
  • 开辟的是一块内存空间,有利于访问速度。
  • #include<stdio.h>
    #include<stdlib.h>

    struct Std
    {
    int a;
    int arr[];
    };

    int main()
    {
    struct Std* p = (struct Std*)malloc(sizeof(struct Std) + 5 * sizeof(int));
    if (p == NULL)
    {
    perror("malloc");
    return 1;
    }
    p->a = 77;
    int i = 0;
    for (i = 0;i < 5;i++)
    {
    p->arr[i] = i + 1;
    }
    struct Std* ptr = (struct Std*)realloc(p,sizeof(struct Std) + 10 * sizeof(int));
    //对柔性数组的长度进行扩容
    if (ptr == NULL)
    {
    perror("realloc");
    return 2;
    }
    p = ptr;
    ptr = NULL;
    for (i = 5;i < 10;i++)
    {
    p->arr[i] = i + 1;
    }
    for (i = 0;i < 10;i++)
    {
    printf("%d ",p->arr [i]);
    }
    free(p);
    p = NULL;
    return 0;
    }

    赞(0)
    未经允许不得转载:171主机测评 » C语言-动态内存管理
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址