【C语言】动态内存分配,2021年大厂Java面经

本文详细介绍了C语言中动态内存分配的几个关键函数:malloc、calloc、realloc和free。讲解了它们的使用方法、区别及常见错误,包括动态内存与静态内存的对比,以及在实际编程中应注意的事项,如防止NULL指针解引用等。
摘要由CSDN通过智能技术生成

文章目录

  • 【C语言】动态内存分配

    • 一、malloc 与free函数
  • 二、calloc

  • 三、realloc

  • 四、常见的动态内存的错误

本期,我们将讲解malloc、calloc、realloc以及free函数。

这是个动态内存分配函数的头文件都是 <stdlib.h>

c语言中动态分配内存的函数,可能有些初学c语言的人不免要问了:我们为什么要通过函数来实现动态分配内存呢?

首先让我们熟悉一下计算机的内存吧!在计算机的系统中大致有这四个内存区域:

1)栈:在栈里面储存一些我们定义的局部变量以及形参(形式参数);

2)字符常量区:主要是储存一些字符常量,比如:char *p=”hello world”;其中”hello world”就储存在字符常量区里面;

3)全局区:在全局区里储存一些全局变量和静态变量;

  1. 堆:堆主要是通过动态分配的储存空间,也就是我们接下需要讲的动态分配内存空间。

静态内存和动态内存的比较:

  • 静态内存是有系统自动分配,由系统自动释放。 静态内存是在分配的。(例如:函数里的局部变量)

  • 动态内存是由程序员手动分配,手动释放。 动态内存是在分配的。(例如:用C语言写链表时,需要自己对Node结点分配内存空间)

一、malloc 与free函数


void* **malloc( size_t ** size);

返回类型: void*,也就是说这个函数的可以返回所有类型的指针形式。只需要在开辟空间的时候进行强制类型转换一下即可。

函数参数:size_t size, 这个参数就是告诉这个函数,你需要开辟多少个字节的内存空间。

void free(void* memblock) ;

没有返回参数。

函数参数:void* memblock, free函数可以接收来自所有类型指针的 动态分配 的 内存空间。

一切以栗子来描述吧:

#include <stdlib.h>

#include <stdio.h>

int main()

{

//开辟10个int类型的空间

int* arr = (int*)malloc(10 * sizeof(int)); //切记这里给的大小,是10 * int(4个字节)

int i = 0;

if (arr == NULL)

{

perror(“malloc”); //有可能,malloc开辟空间失败,则malloc会返回NULL

return 1;

}

for (i = 0; i < 10; i++)

*(arr + i) = i; //放入数据 0 …… 9

for (i = 0; i < 10; i++)

printf("%d ",*(arr + i));

//记得释放所开辟的空间

free(arr);

return 0;

}

二、calloc


void* __calloc (size_t num, size_t** size );

返回类型:与

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

malloc函数是一样的,就不在多说了。

函数参数:size_t num, 需要开辟多少个元素的空间。

​ size_ size, 每一个元素,所占用的内存空间是多少个字节。

:与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。

栗子:

#include <stdlib.h>

#include <stdio.h>

int main()

{

//还是申请10个int类型的内存空间

int* arr = (int*)calloc(10, sizeof(int));

if (arr == NULL)

{

perror(“calloc”); //calloc开辟空间的话,会返回NULL

return 1;

}

//不做赋值运算,直接输出刚开辟的空间,看是否是已经初始化为0了

int i = 0;

for (i = 0; i < 10; i++)

printf("%d ",*(arr + i));

//记得释放空间

free(arr);

return 0;

}

三、realloc


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

作用: Reallocate memory blocks.(重新分配内存块)

  • memblock是需要调整的内存地址

  • size调整之后新大小

  • 返回值为调整之后的内存起始位置。

  • 这个函数调整原内存空间大小的基础_上,还会将原来内存中的数据移动到新的空间。

  • realloc在调整内存空间的是存在两种情况:

情况1 :原有空间之后有足够大的空间

假设我还想为“红色框内的内存空间,扩大一倍,并且在这块空间的后面,是有足够的空间。所有realloc函数会在这紧挨这红色框后面直接开辟空间。并且返回的还是红色框的首元素地址。

情况2: 原有空间之后没有足够大的空间

此时,如果我还想为红色框的内存空间进行扩大,此时红色框后面紧挨着的空间已经被其他程序所占用了,此时想开辟空间的话,只能将现在这块空间先释放掉(realloc会自动释放),再去其他大一点的地方进行开辟空间。

如图:

:realloc函数,有一个很值得注意的地方,看如下代码:

int main()

{

int* arr = (int*)malloc(5 * sizeof(int)); //先开辟5个int类型的空间

if (arr == NULL)

return 1;

//此时,我觉得malloc开辟的空间小了,我想增加

arr = (int*) realloc(arr, 10);

free(arr);

return 0;

}

大家觉得,这段代码,有什么弊端?

分析:

在第8行,realloc函数,去调整arr的空间。他是先查看arr后面的内存空间是否够用,如果不够用的话,会去寻找其他大一点的地方去开辟空间。假设此时我的内存已经满了,此时realloc返回的是NULL。

也就是说,我本来想增容,结果没增成功,还把以前空间里的数据弄丢了。

所以在使用realloc函数时,先使用一个临时变量进行保存一下,如果返回不是NULL,我们在把返回的内存地址赋值给arr即可。

如下:

int main()

{

int* arr = (int*)malloc(5 * sizeof(int)); //先开辟5个int类型的空间

if (arr == NULL)

return 1;

//此时,我觉得malloc开辟的空间小了,我想增加

int* tmp = NULL;

tmp = (int*) realloc(arr, 10);

if (tmp != NULL)

arr = tmp;

free(arr);

return 0;

}

四、常见的动态内存的错误


  • 对NULL进行解引用操作

int main()

{

int* arr = (int*)malloc(10 * sizeof(int));

*arr = 10; //没有对arr进行NULL的判断

free(arr);

(arr == NULL)

return 1;

//此时,我觉得malloc开辟的空间小了,我想增加

int* tmp = NULL;

tmp = (int*) realloc(arr, 10);

if (tmp != NULL)

arr = tmp;

free(arr);

return 0;

}

四、常见的动态内存的错误


  • 对NULL进行解引用操作

int main()

{

int* arr = (int*)malloc(10 * sizeof(int));

*arr = 10; //没有对arr进行NULL的判断

free(arr);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值