0
点赞
收藏
分享

微信扫一扫

C语言动态内存开辟

@TOC

序言

在C语言中,我们经常使用数组,但是当我们使用数组时,我们在内存中开辟的大小已经固定下来的,所以这就引出今天的内容 -- 动态内存开辟

动态内存

什么是动态内存开辟

说的简单点就是我们可以任意开辟我们的空间,即使后期我们发现内存不够用了也可以继续增加

动态内存的特点是什么

数组是在栈区上开辟空间,而动态内存是在堆区上开辟空间

如何进行动态内存开辟

在这里C语言提供了三个函数,这些函数都在标准库stdlib.h,他们分别有各自的作用,我这里先让大家认识一下,后面细说

  1. malloc 函数
  2. calloc 函数
  3. realloc 函数

malloc函数

malloc 所执行的内存分配基于字节数而不是类型,其返回类型为 void 指针(void *),表示该指针所指向区域的数据类型未知。C++ 由于其强类型系统,实际使用该指针时需要进行强制类型转换,而 C 语言中则不必进行。

在这里插入图片描述

例一

开辟一个40个字节的空间,将1-10放到空间中

int main()
{
    int* p = (int*)malloc(40);
    if (p != NULL)
    {
        for (int i = 0; i < 10; i++)
        {
            p[i] = i + 1;
        }
        for (int i = 0; i < 10; i++)
        {
            printf("%d ", p[i]);
        }
    }
    free(p);
    p = NULL;
    return 0;
}

在这里插入图片描述

这里我们会发现一些和我们期望不太一样的东西,我们一点点说

判断开辟的空间是不是空指针

实际上如果我们开辟的空间太大,我们是开辟不出来的,而且编译器会给我们返回一个NULL

int main()
{
    int* p = (int*)malloc(1000000000000000000);
    if (p == NULL)
    {
        printf("开辟的空间太大,无法开辟\n");
    }
    return 0;
}

在这里插入图片描述

free

正所谓有借有还,内存也是如此,我们开辟的了空间后,要是不再使用了应该将他释放掉,要不然这块空间被占据着,无法被其他人使用

free的作用就是将它的空间释放掉

将释放的变量置为NULL

当我们free掉内存空间后,p仍旧指向这片空间,要是我们不小心再次使用,就会发生非法访问,就像你的前女/男友一样,你或许记者她/他的号码,要是你再骚扰她/他,这就很不地道

int main()
{
    int* p = (int*)malloc(40);
    printf("%p\n", p);
    free(p);
    printf("%p\n", p);
    return 0;
}

在这里插入图片描述

calloc函数

calloc函数和malloc函数作用差不多,不过参数有些不同

参数不同

void *calloc( size_t num, size_t size );

  • size_t num 表示要开辟的个数
  • size_t size表示开辟一个占据的字节数

int p = (int)calloc(4,4)表示开辟四个,每个占据4个字节

在这里插入图片描述

作用有些差异

  • malloc开辟的空间里面是随机值
  • calloc开辟的空间并且初始化了,初始化为0
int main()
{
    int* p = (int*)calloc(4,4);
    if (p != NULL)
    {
        printf("%d %d %d %d\n", p[0], p[1], p[2], p[3]);
    }

    free(p);
    p = NULL;
    return 0;
}

在这里插入图片描述

realloc函数

要是前面两个函数是开辟,纳么realloc函数可以理解为追加,要是我们第一次开辟的空间太小,我们就可以使用realloc函数进行扩大

参数

void realloc( void memblock, size_t size );

  • void *memblock 第一次开辟空间的地址,要是没有第一次开辟,可以写成NULL 相当于第一次开辟了
  • size_t size 开辟空间的总大小 == 第一次的 + 追加的
首次开辟
int main()
{

    int* p = (int*)realloc(NULL, 80);
    free(p);
    p = NULL;
    return 0;
}
追加
int main()
{
    int* p = (int*)malloc(40);
    int* tmp = (int*)realloc(p, 80);
    if (tmp != NULL)
    {
        p = tmp;
    }
    free(p);
    p = NULL;
    return 0;
}

realloc重新开辟

要是我们追加的空间太大,编译器会自动开辟一块新的内存,并且将第一次开辟的值赋到新空间中,要是够了,就在后面追加

int main()
{
    int* p = (int*)malloc(40);
    if (p == NULL)
    {
        return 0;
    }
    for (int i = 0; i < 10; i++)
    {
        p[i] = i + 1;
    }
    int* tmp = (int*)realloc(p, 8000);
    if (tmp != NULL)
    {
        if (tmp == p)
        {
            printf("为重新开辟\n");
        }
        else
        {
            printf("重新开辟了了一块新内存\n");
            for (int i = 0; i < 10; i++)
            {
                printf("%d ", tmp[i]);
            }
        }
        p = tmp;
    }

    free(p);
    p = NULL;
    return 0;
}

在这里插入图片描述

总结

  1. 每次开辟后不用了一定要free掉
  2. 三个函数的返回值都是void* ,参数不同
举报

相关推荐

0 条评论