【C语言】动态内存分配

目录

前言

malloc

free

calloc

realloc

常见的动态内存错误


前言

内存有三个区:堆区、栈区、静态区

堆区存储:动态内存分配

栈区:局部变量、函数的形参

静态区:全局变量、静态变量、static修饰的变量

接下来介绍动态内存分配涉及到的四个函数,malloc、free、calloc、realloc,他们在stdlib.h这个头文件里面使用的时候需要include。

malloc

原型:void* malloc (size_t size);

注意:

  1. 如果开辟成功,则返回一个指向开辟好空间的指针。
  2. 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。

free

void free (void* ptr);

注意:

  1. 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
  2. 如果参数 ptr 是NULL指针,则函数什么事都不做。

接下来用一个简单的例子来试一下这两个函数:

eg:


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

int main()
{
    int* ptr = NULL;
    ptr = (int*)malloc(10*sizeof(int));//开辟10个int型的空间,用ptr指向这个空间的开头。
    if(!ptr)//ptr == NULL -->这里是检查开辟是否成功,失败会返回NULL
        perror("malloc failed");
    int i = 0;
    for(i=0; i<10;i++)//遍历这是个空间 并给他们赋值
    {
     *(ptr+i) = i;
    }
   for (i = 0; i < 10; i++)//打印刚才存进去的值,你们可是试试多遍历一个数会出现什么情况?
    {
           printf("%d ", *(ptr+i));
    }
    
    free(ptr);
    ptr = NULL;//使用后该指针变量一定要重新指向NULL,防止悬空指针(失效指针)出现,有效规避错误操作。
    return 0;
}

大家可以自己复制编译一下。

calloc

void* calloc (size_t num, size_t size);

注:

  1. 函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。
  2. 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。

eg:


int main()
{
    int* ptr = NULL;
    ptr = (int*)calloc(10, sizeof(int));//开cccc辟10个int型的空间,用ptr指向这个空间的开头。
    if (!ptr)//ptr == NULL -->这里是检查开辟是否成功,失败会返回NULL
        perror("malloc failed");
    int i = 0;
    
    for (i = 0; i < 10; i++)
    {
    printf("%d ", *(ptr+i));
    }
    free(ptr);
    ptr = NULL;//使用后该指针变量一定要重新指向NULL,防止悬空指针(失效指针)出现,有效规避错误操作。
    return 0;
}

realloc

void* realloc (void* ptr, size_t size);

注:

1.ptr 是要调整的内存地址,size 调整之后新大小,返回值为调整之后的内存起始位置。

此时会发生两种情况:

  • 情况1:原有空间之后有足够大的空间,他就会接着在后面开辟空间。
  • 情况2:原有空间之后没有足够大的空间,它会找到足够大的空间,并把原本的数据拷贝过去。

这里大家了解就行。

eg:


int main()
{
    int* ptr = NULL;
    ptr = (int*)malloc(10*sizeof(int));//开辟10个int型的空间,用ptr指向这个空间的开头。
    if(!ptr)//ptr == NULL -->这里是检查开辟是否成功,失败会返回NULL
        perror("malloc failed");
    int i = 0;
    for(i=0; i<10;i++)//遍历这是个空间 并给他们赋值
    {
     *(ptr+i) = i;
    }
    int* ptr1 = NULL;
    ptr1 = (int* )realloc(ptr, 5*sizeof(int));//此时就可以直接使用ptr1来进行操作了
    if(!ptr1)//ptr == NULL -->这里是检查开辟是否成功,失败会返回NULL
        perror("realloc failed");
    for(;i<15;i++)
    {
        *(ptr1+i) = i;
    }
    
    
    free(ptr1);
    ptr1 = NULL;//使用后该指针变量一定要重新指向NULL,防止悬空指针(失效指针)出现,有效规避错误操作。
    return 0;
}

当指针赋给ptr1时,就不用管ptr了,最后也不用在free(ptr),只用free掉ptr1就行。

常见的动态内存错误

  1. 对空指针解引用(开辟失败后未检测就直接使用)。
  2. 对动态开辟的空间越界访问(申请的空间小于你打算访问的空间)。
  3. 对非动态开辟的空间进行free释放//应该没人会这样吧。
  4. 使用free释放一块空间的一部分//记得少让指向空间的指针进行++操作,要进行这类操作时记得用其他指针指向这个地址,防止内存泄漏。
  5. 对同一个动态内存多次释放。
  6. 忘记释放动态内存。
  7. 要调用接口进行动态内存创建时,要记得传地址而不是传值,这样比较方便。

eg:

error:


void Get(char* p)
{
    p = (char*)malloc(100);
}
void test()
{
    char* str = NULL;
    Get(str);//以变量的方式传参;无法做到str的修改;
    strcpy(str, "hello");
    printf(str);
    free(str);
    str = NULL;
}

get里面的p是个局部参数 一旦出了这个函数他就失效了,也就是说他的生命周期其实就只有这一个get函数而已。

correct1:


void Get(char** p)
{
    *p = (char*)malloc(100);
}
void test()
{
    char* str = NULL;
    Get(&str);//以变量的方式传参;无法做到str的修改;要传地址
    strcpy(str, "hello");
    printf(str);
    free(str);
    str = NULL;
}

correct2:


char* Get(char* p)
{
    p = (char*)malloc(100);
    return p;
}
void test()
{
    char* str = NULL;
    char* str1 = NULL;
    str1 = Get(str);//以变量的方式传参;无法做到str的修改;说实话 我感觉什么都不用传也行
    strcpy(str1, "hello");
    printf(str1);
    free(str1);
    str1 = NULL;
}

correct2--修改版本:


char* Get()
{
    int* p = NULL;
    p = (char*)malloc(100);
    return p;
}
void main()
{
    char* str = NULL;
    str = Get();//直接接收返回的指针
    strcpy(str, "hello");
    printf(str);
    free(str);
    str = NULL;
}

结束!如有错误,请及时指出,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

April.19th

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

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

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

打赏作者

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

抵扣说明:

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

余额充值