【C语言】动态内存分布

前言

本博文仅作为本人总结学习 C语言动态内存分配知识学习使用。在总结过程中参考了多篇博客。

参考博客:

https://www.cnblogs.com/ericling/p/11746972.html

https://blog.csdn.net/MarcoAsensio/article/details/85937002

概述

数组是固定数量的值的集合,在声明数组的大小之后,无法更改。有时,数组大小可能不够,就需要动态扩容。解决此问题,可以在运行时手动分配内存。这在C编程中称为动态内存分配

在C语言中,内存分为四块存储区域,栈,堆,静态存储区,代码区。堆内存是一种在需要时申请,在不需要时释放的内存块,都是由程序员来完成的,今天我们来探讨一下动态分配堆内存的库函数,这些库函数包含在头文件 <stdlib.h>中。

动态分配存储器涉及到的库函数有

  • malloc()
  • calloc()
  • realloc()
  • free()

1.malloc函数

malloc的全称是 memory allocation,中文叫动态内存分配,用于申请一块连续的指定大小的内存块区域以 void* 类型返回分配的内存区域地址,当无法知道内存具体位置的时候,想要绑定真正的内存空间,就需要用到动态的分配内存。

函数的原型是 extern void *malloc(unsigned int num_bytes);

下面我们编写一段代码用malloc函数随机分配40个字节的存储空间,并将存储空间的地址打印出来,

malloc()的语法

ptr = (castType*) malloc(size);

示例:

ptr = (int*) malloc(100 * sizeof(float));

上面的语句分配了400 个字节的内存。这是因为 float 的大小为 4 个字节。并且,指针ptr保存分配的存储器中的第一个字节的内存地址。

如果无法分配内存,则表达式将产生一个 NULL 指针。

在这里插入图片描述

然后我们找到这块内存地址,

在这里插入图片描述
发现已经生成了40个字节大小未被初始化的内存空间,malloc函数的作用就是开辟规定大小的堆内存空间。

2.calloc函数

在内存的动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。

函数的原型是 void *calloc(size_t n, size_t size);

名称“ calloc”代表连续分配,contiguous allocation。

malloc()函数分配内存,但不初始化内存。而calloc() 函数分配内存并将所有位初始化为零。

同样地,我们编写一段代码用calloc函数随机分配40个字节的存储空间,并将存储空间的地址打印出来,

calloc()的语法

ptr = (castType*)calloc(n, size);

示例:

ptr = (float*) calloc(25, sizeof(float));

上面的语句为 float 类型的 25 个元素在内存中分配了连续的空间。

在这里插入图片描述

然后我们找到这块内存地址,

在这里插入图片描述

然后我们惊奇的发现用calloc函数开辟的40个字节的堆内存已经被初始化为0,这便是malloc和calloc函数的区别。

3.free()

使用calloc()或malloc()不单独释放创建的动态分配内存,必须明确使用free()释放空间。

free()的语法

free(ptr);

该语句释放由指向的内存中分配的空间ptr。

// Program to calculate the sum of n numbers entered by the user
#include <stdio.h>
#include <stdlib.h>
int main()
{
    int n, i, *ptr, sum = 0;
    printf("Enter number of elements: ");
    scanf("%d", &n);
    ptr = (int*) malloc(n * sizeof(int));
 
    // if memory cannot be allocated
    if(ptr == NULL)                     
    {
        printf("Error! memory not allocated.");
        exit(0);
    }
    printf("Enter elements: ");
    for(i = 0; i < n; ++i)
    {
        scanf("%d", ptr + i);
        sum += *(ptr + i);
    }
    printf("Sum = %d", sum);
  
    // deallocating the memory
    free(ptr);
    return 0;
}

在这里,我们已为n个数字动态分配了内存
示例2: calloc()和free()

// Program to calculate the sum of n numbers entered by the user
#include <stdio.h>
#include <stdlib.h>
int main()
{
    int n, i, *ptr, sum = 0;
    printf("Enter number of elements: ");
    scanf("%d", &n);
    ptr = (int*) calloc(n, sizeof(int));
    if(ptr == NULL)
    {
        printf("Error! memory not allocated.");
        exit(0);
    }
    printf("Enter elements: ");
    for(i = 0; i < n; ++i)
    {
        scanf("%d", ptr + i);
        sum += *(ptr + i);
    }
    printf("Sum = %d", sum);
    free(ptr);
    return 0;
}

4.realloc函数

先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。

函数的原型是extern void *realloc(void *mem_address, unsigned int newsize);

下面我们编写一段代码,先用malloc函数申请40个字节的堆内存,再用realloc函数进行扩增,如果我们只扩增4个字节,

如果动态分配的内存不足或超出要求,则可以使用该realloc()功能更改以前分配的内存的大小。

realloc()的语法

ptr = realloc(ptr, x);

在这里,ptr以新的大小x重新分配。

示例3: realloc()

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int *ptr, i , n1, n2;
    printf("Enter size: ");
    scanf("%d", &n1);
    ptr = (int*) malloc(n1 * sizeof(int));
    printf("Addresses of previously allocated memory: ");
    for(i = 0; i < n1; ++i)
         printf("%u\n",ptr + i);
    printf("\nEnter the new size: ");
    scanf("%d", &n2);
    // rellocating the memory
    ptr = realloc(ptr, n2 * sizeof(int));
    printf("Addresses of newly allocated memory: ");
    for(i = 0; i < n2; ++i)
         printf("%u\n", ptr + i);
  
    free(ptr);
    return 0;
}

运行该程序时,输出为:

输入大小:2
先前分配的内存的地址:26855472
26855476

输入新的尺寸:4
新分配的内存地址:26855472
26855476
26855480
26855484

在这里插入图片描述

我们会发现两个内存的地址是相同的,但如果我们扩增400个字节,

在这里插入图片描述

我们会发现这两个内存的地址是不相同的,这说明,使用realloc函数之前会先判断原内存后面内存够不够用,如果够用就会直接接在原内存后面进行扩增,如果不够用就会先将原内存的内容拷贝的一段新的内存,然后释放原内存,再在新内存后面进行扩增,这就是realloc函数的特点。

注: 内存地址内容的查找: VS,调试 --> 窗口 --> 内存

总结

  1. malloc
    malloc 动态分配内存,不初始化,如果无法分配内存,则返回 NULL。
int n, *ptr = 0;
printf("Enter number of elements: ");
scanf("%d", &n);
ptr = (int*) malloc(n * sizeof(int));
  1. calloc

calloc 动态分配内存,初始化所有 bit 为 0,如果无法分配内存,则返回NULL

int n, *ptr = 0;
printf("Enter number of elements: ");
scanf("%d", &n);
ptr = (int*) calloc(n, sizeof(int));

free释放内存

free(ptr);

realloc重新分配内存

ptr = realloc(ptr, n * sizeof(int));
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何为xl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值