进阶C语言 第五章-------《动态内存管理》 (malloc、free,calloc、realloc、柔性数组、C/C++程序在内存)知识点+完整思维导图+基本练习题+深入细节+通俗易懂+建议收藏(一0

简介: 进阶C语言 第五章-------《动态内存管理》 (malloc、free,calloc、realloc、柔性数组、C/C++程序在内存)知识点+完整思维导图+基本练习题+深入细节+通俗易懂+建议收藏(一0

绪论

       书接上回,本章来到动态内存管理,这章的知识相较于结构体来说来简单一点,但是有许多地方需要注意不能马虎,并且该章的知识也比较重要,通过名称可以知道动态的内存管理,这样就可以对内存有一个很方便的管理方法!

image.png

所以安全带系好,发车啦(建议电脑观看)。



思维导图:

image.png


要XMind思维导图的话可以私信哈


目录


1.动态内存分配存在的意义

2.动态内存函数

2.1malloc

2.2free

2.3callloc

2.4realloc

3.动态内存常见的错误

3.1对NUL指针的解应用操作

3.2对动态内存开辟的空间越界访问

3.3对非动态开辟的内存进行free释放

3.4使用free释放动态内存开辟的一部分空间

3.5对同一块动态内存空间多次释放

3.6动态内存空间的忘记释放

4.动态内存常见问题、笔试题

5.C/C++程序在内存中的内存开辟

6.柔性数组

1.动态内存分配存在的意义

为什么要有动态内存管理?

下面通过对比来解释:

在我们一般申请内存的时候都是通过创建变量类型来申请的空间

如:int(4byte)、char(1byte)、int [ ]、结构体、联合体、枚举......

而这些内存的空间当我们创建好后他就固定死了,就比较的局限(死板)。

现在C语言提供了一种方式就是动态内存管理(函数)当我们需要时就创建一定的空间,当空间不够后又可以再次的补充其空间,当然当空间过大也可以减小空间的大小

2.动态内存函数

2.1malloc

知识点:

image.png

对于malloc函数来说他的类型是void *malloc(size_t);

用法:申请一个连续可用的size字节大小的空间,开辟成功时返回指向这块空间的指针

头文件:#include<stdlib.h>

所以一般的用法是要将返回来的void * 强转成自己所需要的指针类型

如:

int main()
{
    //当你要开辟多个以整型大小为基础的空间时
    int * ptr = (int *)malloc(sizeof(int) * 10);//当然你也可以直接在()内写成“40”byte
    //对于上面因为你需要开辟的是整形个大小的空间所以最后将返回的指针强转成整形指针类型
    //并且ptr也要是整形指针这是你所要用的,你甚至可以把它想像成开辟了一个大小为10的整形数组
    return 0;
}

为什么这样写我已经写上了注释

细节:

既然是申请那就有可能会失败,所以当申请失败的时候系统会返回一个空指针(NULL)

所以在我们写完后要加上一个判断,判断其是否申请成功

    if (ptr == NULL)
    {
        printf("%s\n", strerror(errno));//打印错误
        //perror("ptr");//打印错误
        return 0;
    }

image.png


不能开辟0byte的空间

判断空间是否申请成功

用free释放申请好的空间(并且将其指针置为空)

练习        

用动态内存分配的空间来打印打印1~10:

分析:

因为最终传回来的是指针所以就可以通过指针的方法来进行内存的访问,并且所开辟的大小也是以整形大小一个个开辟的,所以直接+1即可

 #define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
    //当你要开辟多个以整型大小为基础的空间时
    int* ptr = (int*)malloc(40);
    if (ptr == NULL)
    {
        perror("ptr");//打印错误
        return 0;
    }
    for(int i = 0; i<10 ; i++)
    {
        *(ptr+i) = i +1;
       printf("%d ",*(ptr + i)); 
    }
    free(ptr);//释放向内存中借的空间
  ptr = NULL;
    return 0;
}


2.2free

知识点:

函数:void free (void* ptr);

当我们向操作系统借了的空间所以用完了后我们需要将其归还(若不归还的话对这空间再你没有结束程序的过程中都处于被借的状态也就浪费了这片没有用的空间)

用法:释放所传递过来的动态内存开辟的指针所指向的空间

细节:

对于free所释放的空间,虽然将其所存的内存归还给了操作系统,但ptr所指地址并不会被其改变,所以为了防止我们后面不小心还使用ptr这个地址指向的被已经释放的内存,所以需要再将ptr置为NULL

free(ptr);
ptr = NULL;

当所传递过来的是NULL时,free什么都不做。

不能释放不是动态内存开辟的空间

2.3callloc

知识点:

void* calloc (size_t num, size_t size);

该函数的意义和malloc一样,都是用来开辟空间的。

但是其参数不相同,num表示的是元素个数,而size表示的是每个元素的大小,返回值一样

所以对于之前用malloc开辟的10个整形大小的空间(40byte)就还可以写成calloc形式的:

int main()
{
    int* p = (int*)calloc(10, sizeof(int));
    if (p == NULL)
    {
        perror("p");
        return 0;
    }
//使用
    free(p);
    p = NULL;
    return 0;
}

细节:

同样的calloc也需要判断是否申请成功

用free释放申请好的空间(并且将其指针置为空)

image.png

通过对比上面两段代码我们可知:

malloc在申请往空间后不会对这部分空间有任何作业

calloc在申请完空间后会对这部分全部空间初始化为0

所以在我们使用时可以通过他们不同的类型进行选择使用

上面的malloc、calloc都是开辟内存的空间的,而下面的realloc就是修改开辟的内存空间

2.4realloc

知识点:

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

第一个参数是要调整的内存地址(由malloc、calloc、realloc开辟的内存块),第二个参数是所要调整的新的空间的大小(size个字节),返回情况是一样的

具体使用如下

int main()
{
  int* p = (int*)malloc(sizeof(int) * 5);
  if (p == NULL)
  {
    perror("malloc");
    return 1;
  }
  for (int i = 0; i < 5; i++)
  {
    *(p + i) = i + 1;
    printf("%d ", *(p + i));
  }
  int* ptr = (int *)realloc(p, sizeof(int) * 10);
  if(ptr != NULL)//当等于空指针时就没有动作了不用管ptr
  {
    p = ptr;
        ptr = NULL;
  }
  for (int i = 5; i < 10; i++)
  {
    *(p + i) = i + 1;
    printf("%d ", *(p + i));
  }
  free(p);
  p = NULL;
  return 0;
}

细节:

在上述代码中我们可以发现在用realloc增加或减少动态内存的空间后 返回时 接收返回值的指针是一个新的指针(int * ptr)而不是所要改变的那片空间的地址(p),这是因为:realloc开辟空间时分着两种情况:

1.当realloc所要开辟的空间在原始空间的后面有足够的空间让其使用时那就直接在原始位置处开辟

image.png

2.当realloc所要开辟的空间在原始位置后面没有足够的空间让其使用,此时就会寻找一个放的下的空间,并且将原数据拷贝过去,并且释放掉原空间和返回新的地址

image.png

3.就是因为可能的两种情况,所以为了避免第二种释放原位置返回新地址,所以用一个新指针接收其返回的地址,如果直接写成  p = realloc(p,sizeof(int)*10)的话 假如开辟没有成功那就会返回NULL而原本还有的5个空间大小直接就没了(p = NULL)。


当第一个参数传的是NULL时其用法和malloc类型开辟申请一块新的空间:

realloc(NULL,40) == malloc(40)  ;

并且返回指向这块空间的地址

相关文章
|
14天前
|
程序员 C语言 开发者
pymalloc 和系统的 malloc 有什么区别
pymalloc 和系统的 malloc 有什么区别
|
7天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
25 4
|
10天前
|
程序员 C语言 开发者
pymalloc 和系统的 malloc 有什么区别?
pymalloc 和系统的 malloc 有什么区别?
|
1月前
|
程序员 编译器 C语言
C中的 malloc 和C++中的 new 有什么区别
在C语言中,`malloc`函数用于在运行时分配内存,返回指向所分配内存的指针,需显式包含头文件 `&lt;stdlib.h&gt;`。而在C++中,`new`不仅分配内存,还对其进行构造初始化,且直接使用类型声明即可,无需额外包含头文件。`new`还支持数组初始化,能更好地融入C++的面向对象特性,而`malloc`仅作为内存分配工具。使用完毕后,`free`和`delete`分别用于释放`malloc`和`new`分配的内存。
51 21
|
27天前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
1月前
|
C语言
C语言学习笔记-知识点总结上
C语言学习笔记-知识点总结上
74 1
|
1月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
154 1
|
1月前
一刻也没有为它哀悼~接下来登场的是动态内存分配的malloc与realloc以及free函数
一刻也没有为它哀悼~接下来登场的是动态内存分配的malloc与realloc以及free函数
65 0
|
1月前
|
存储 编译器 C++
【C++】掌握C++类的六个默认成员函数:实现高效内存管理与对象操作(三)
【C++】掌握C++类的六个默认成员函数:实现高效内存管理与对象操作
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
33 3