C语言——动态内存函数(malloc、calloc、realloc、free)

简介: C语言——动态内存函数(malloc、calloc、realloc、free)

前言:

在C语言中,动态内存函数是块重要的知识点。以往,我们开辟空间都是固定得,数组编译结束后就不能继续给它开辟空间了,开辟的空间满了,就不能在开辟空间了(就是不能在添加数据了)。学习本文章,我们就可以解决这个问题,向内存申请空间,满啦可以继续申请空间。


一、malloc函数

需要头文件——<stdlib.h>



浏览器直接翻译:

malloc函数(动态内存开辟的函数):

void* malloc(size_t size);

功能:

这个函数向内存申请一个连续可用的空间,并返回指向这块空间的指针。


如果开辟成功,则返回一个指向开辟好空间的指针。

如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。

返回值的类型是void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候由使用者自己决定。

如果size为0,malloc的行为是标准还是未定义的,由编译器决定。

malloc申请的空间,当程序退出时,要还给操作系统,当程序不退出,动态申请的内存,不会主动释放,需要用free函数来释放。

malloc申请的内存空间:

malloc申请到空间后,直接返回这个空间的首地址,不会初始化空间的内容。

举个例子:

#include <stdio.h>
#include <stdlib.h>
int main()
{
//变长数组的知识点(vs不能用,gcc可以用)
    //int num = 0;
    //scanf("%d", &num);
    //int arr[num] = { 0 };
    int* ptr = NULL;
    ptr = (int*)malloc(40);
    if (ptr == NULL)//判断ptr指针是否为空
    {
        perror("malloc");
        exit; 
    }
    else
    {
        int i = 0;
        for (i = 0; i < 10; i++)//给开辟的空间赋值
            ptr[i] = i + 1;
    }
    free(ptr);//释放ptr指向的空间
    ptr = NULL;//让ptr指向空
    return 0;
}

二、calloc函数

需要头文件——<stdlib.h>

浏览器直接翻译:

calloc函数(动态内存分配函数):

void* calloc(size_t num, size_t size);

功能:

  • 函数的功能是,为num个大小为size元素开辟一块空间,并且把空间的每一个字节初始化为0.
  • 与malloc函数的区别,只在于calloc函数会在返回地址之前把申请空间的每一个字节初始化为0.
    举个例子:
#include <stdio.h>
#include <stdlib.h>
int main()
{
    int* p = (int*)calloc( 10,sizeof(int));
    if (p == NULL)//成立,开辟失败
    {
        perror("calloc");
        exit;
    }
    free(p);
    p = NULL;
    return 0;
}

p指向的地址:

三、realloc函数

需要头文件——<stdlib.h>

浏览器直接翻译:

realloc函数(动态内存管理更加灵活):

有时候我们发现过去申请的空间小了,有时候我们会觉得过去申请的空间过大,为了合理使用内存,我们一定要对内存的大小做灵活的调整。realloc函数可以做到对动态开辟内存大小进行调整。

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

功能:


ptr是要调整的内存地址。

size是调整后的新大小。

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

这个函数在调整原空间大小的基础上,还会将原来的数据移到新的空间。

注意:

realloc调整内存空间有两种情况。

情况1:原有空间之后有足够大的空间(原地扩容)。

当是情况1的时候,要扩展内存就直接在原有内存之后直接追加空间,原来空间的数据不发生改变。


情况2:原有空间后面没有足够大的空间(异地扩容)。

当是情况2的时候,原有空间后面没有足够多的空间时,扩展的方法是:在堆空间上另外找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。

所以我们在使用realloc函数的时候一定要注意:

1、开辟新的空间。

2、 会将旧的空间数据拷贝到新的空间。

3、释放旧的空间。

4、返回新空间的起始地址。

举个例子:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int* ptr =(int*) malloc( 100 );
    if (ptr != NULL)
    {
//可以使用这个空间
    }
    else
    {
        perror("malloc");
        exit;
    }
    //扩展空间
    int* p = (int*)realloc(ptr, 1000);//可能增容失败
    if (p != NULL)
    {
        //增容成功
        ptr = p;//p指向的空间交给ptr去维护
    }
    free(ptr);//把开辟早堆上的空间释放掉
    ptr = NULL;
    return 0;
}

四、free函数

需要头文件——<stdlib.h>

浏览器直接翻译:

free函数(释放动态开辟的内存):

void* free(void* ptr);

功能:

  • 如果参数ptr指向的那个空间不是动态开辟的,那free函数的行为是未定义的。
  • 如果参数ptr是NULL指针,则函数什么事都不做。
相关文章
|
21天前
|
存储 C语言 开发者
【C语言】字符串操作函数详解
这些字符串操作函数在C语言中提供了强大的功能,帮助开发者有效地处理字符串数据。通过对每个函数的详细讲解、示例代码和表格说明,可以更好地理解如何使用这些函数进行各种字符串操作。如果在实际编程中遇到特定的字符串处理需求,可以参考这些函数和示例,灵活运用。
40 10
|
21天前
|
存储 程序员 C语言
【C语言】文件操作函数详解
C语言提供了一组标准库函数来处理文件操作,这些函数定义在 `<stdio.h>` 头文件中。文件操作包括文件的打开、读写、关闭以及文件属性的查询等。以下是常用文件操作函数的详细讲解,包括函数原型、参数说明、返回值说明、示例代码和表格汇总。
42 9
|
21天前
|
C语言 开发者
【C语言】数学函数详解
在C语言中,数学函数是由标准库 `math.h` 提供的。使用这些函数时,需要包含 `#include <math.h>` 头文件。以下是一些常用的数学函数的详细讲解,包括函数原型、参数说明、返回值说明以及示例代码和表格汇总。
41 6
|
28天前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
232 1
|
18天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
27天前
|
Java
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80
|
28天前
|
Java
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
21 3
|
28天前
|
存储 缓存 监控
Elasticsearch集群JVM调优堆外内存
Elasticsearch集群JVM调优堆外内存
45 1
|
1月前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
2月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
80 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS