【C语言】realloc()函数详解(动态内存开辟函数)

简介: 【C语言】realloc()函数详解(动态内存开辟函数)

一.realloc()函数简介

我们先来看一下cplusplus.com - The C++ Resources Network网站上realloc()函数的基本信息:

1.函数功能

可以看到,realloc()函数的功能是:更改动态分配的内存大小.

即便将内存块移动到新位置(异地扩容),之前内存块的内容也会随之转移到新的位置.但新开辟的部分是未被初始化的.

如我们使用malloc开辟并初始化5个整型,然后使用realloc扩容到10个整型后打印:


2.函数参数

该函数一共有2个参数,分别是:

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

1>.void* ptr

第一个参数的类型是无类型指针(void*),它指向一个要重新分配内存的内存块,该内存块是之前通过调用malloc,calloc或realloc进行动态分配内存的.

如果为空指针,则会分配一个新的内存块,且函数返回一个指向它的指针.

2>.size_t size

第二个参数的类型是无符号整型(size_t),它表示新内存块的大小,以字节为单位.

如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被释放,并返回一个空指针。


3.函数返回值

void*

函数的返回值类型是无类型指针(void*),它的作用是在函数运行结束后返回指向重新分配大小的内存块的指针.如果请求失败了,则会返回一个空指针.


4.函数头文件

该函数包含在头文件<stdlib.h>中.


二.realloc()函数的具体使用

realloc()函数的使用场景是:当我们想调整先前使用malloc(),calloc()或realloc()函数开辟的动态内存的大小时,我们可以使用realloc()函数来实现这一诉求.

1.使用realloc()函数完成动态整型数组空间的扩容

如下,我们使用realloc()函数调整一个有10个元素的整型数组的大小将其改为15个整型元素.

分别给realloc()函数传入:动态开辟的内存块指针(即p),新内存块的大小(即15*sizeof(int)).

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
 
int main()
{
    int* p = (int*)malloc(10*sizeof(int));    //开辟10个整型大小空间
    if (p == NULL)       //如果开辟失败,则打印错误原因
    {
        //打印错误原因的一个方式
        printf("%s\n", strerror(errno));
    }
    else
    {
        int i = 0;
        for (i = 0; i < 10; i++)    //遍历并初始化打印这10个整型空间
        {
            *(p + i) = i;
            printf("%d ", *(p + i));
        }
        //可以正常使用p指针来操作这片空间了
    }
    printf("\n");
    int* p2 = (int*)realloc(p, 15 * sizeof(int));//将这块空间扩容到15个整型
    if (p2 == NULL)
    {
        printf("%s\n", strerror(errno));
    }
    else
    {
        int i = 0;
        for (i = 0; i < 15; i++)    //遍历并打印这15个整型空间
        {
            *(p2 + i)=i;
            printf("%d ", *(p2 + i));
        }
    }
 
    free(p);    //释放p的内存空间
    p = NULL;         //将指针p置为NULL,防止其变成野指针
 
    return 0;
}

在vs编译器中运行查看结果:

可见realloc()函数成功的将malloc()函数开辟的10个整形大小的空间改为15个整型大小的空间了.


2.使用()函数完成动态结构体空间的扩容

创建好结构体变量后,我们给calloc()函数传入:3 , sizeof(PeoInfo)(即3个PeoInfo类型大小的字节数).用来开辟好3个PeoInfo大小的结构体数组.


使用calloc()开辟好空间后我们使用realloc()函数将结构体数组的空间扩容到5个.

realloc()函数传入:ptr , 5*sizeof(PeoInfo)(即5个PeoInfo类型大小的字节数).

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
 
//人的信息-结构体
typedef struct PeoInfo
{
  char name[20];
  int age;
  char sex[5];
  char addr[20];
  char tele[11];//电话11位,留一位给'\0';
}PeoInfo;
 
typedef struct Contact
{
  PeoInfo* data;  //存放人的信息
  int sz;         //用来记录当前已经存放的信息的个数
  int capacity;   //记录当前通讯录的最大容量
}Contact;
 
int main()
{
  Contact con;
  PeoInfo* ptr = (PeoInfo*)calloc(3, sizeof(PeoInfo));   //动态开辟空间
 
  if (ptr == NULL)            //如果开辟失败,则打印错误原因
  {
    perror("InitContact::calloc");
    return;
  }
 
  PeoInfo*ptr2 = (PeoInfo*)realloc(ptr, 5 * sizeof(PeoInfo));
  if (ptr2 == NULL)
  {
    perror("InitContact::realloc");
    return;
  }
 
  free(ptr2);         //使用完后向系统归还动态开辟的内存空间
  ptr2 = NULL;              //将ptr2指针置为空,避免ptr2成为野指针
 
  return 0;
}

在vs编译器中查看结果:

可见realloc()函数成功的将结构体的元素个数由3个改为了5个.


三.realloc()的异地扩容

使用realloc()函数调整内存空间存在两种情况:

  1. 原有空间之后有足够大的空间
  2. 原有空间之后没有足够大的空间

如:图中绿色空间是我们之前动态开辟的内存空间,而现在我们想使用reallo函数将它扩容一倍,

黑色条代表内存条,红色空间代表被其他程序占用的空间,而紫色空间代表待扩容空间.

情况一:

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

情况二:

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


结语

希望这篇realloc()函数详解能对大家有所帮助,欢迎大佬们留言或私信与我交流.

有关更多动态开辟相关知识可以移步:

学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!



C语言动态内存开辟相关库函数思维导图:


相关文章
|
9天前
|
人工智能 Java 程序员
一文彻底搞清楚C语言的函数
本文介绍C语言函数:函数是程序模块化的工具,由函数头和函数体组成,涵盖定义、调用、参数传递及声明等内容。值传递确保实参不受影响,函数声明增强代码可读性。君志所向,一往无前!
12 1
一文彻底搞清楚C语言的函数
|
2月前
|
C语言
【C语言程序设计——函数】亲密数判定(头歌实践教学平台习题)【合集】
本文介绍了通过编程实现打印3000以内的全部亲密数的任务。主要内容包括: 1. **任务描述**:实现函数打印3000以内的全部亲密数。 2. **相关知识**: - 循环控制和跳转语句(for、while循环,break、continue语句)的使用。 - 亲密数的概念及历史背景。 - 判断亲密数的方法:计算数A的因子和存于B,再计算B的因子和存于sum,最后比较sum与A是否相等。 3. **编程要求**:根据提示在指定区域内补充代码。 4. **测试说明**:平台对代码进行测试,预期输出如220和284是一组亲密数。 5. **通关代码**:提供了完整的C语言代码实现
66 24
|
2月前
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
77 16
|
2月前
|
存储 编译器 C语言
【C语言程序设计——函数】分数数列求和2(头歌实践教学平台习题)【合集】
函数首部:按照 C 语言语法,函数的定义首部表明这是一个自定义函数,函数名为fun,它接收一个整型参数n,用于指定要求阶乘的那个数,并且函数的返回值类型为float(在实际中如果阶乘结果数值较大,用float可能会有精度损失,也可以考虑使用double等更合适的数据类型,这里以float为例)。例如:// 函数体代码将放在这里函数体内部变量定义:在函数体中,首先需要定义一些变量来辅助完成阶乘的计算。比如需要定义一个变量(通常为float或double类型,这里假设用float。
46 3
|
2月前
|
存储 算法 安全
【C语言程序设计——函数】分数数列求和1(头歌实践教学平台习题)【合集】
if 语句是最基础的形式,当条件为真时执行其内部的语句块;switch 语句则适用于针对一个表达式的多个固定值进行判断,根据表达式的值与各个 case 后的常量值匹配情况,执行相应 case 分支下的语句,直到遇到 break 语句跳出 switch 结构,若没有匹配值则执行 default 分支(可选)。例如,在判断一个数是否大于 10 的场景中,条件表达式为 “num> 10”,这里的 “num” 是程序中的变量,通过比较其值与 10 的大小关系来确定条件的真假。常量的值必须是唯一的,且在同一个。
32 2
|
2月前
|
存储 编译器 C语言
【C语言程序设计——函数】回文数判定(头歌实践教学平台习题)【合集】
算术运算于 C 语言仿若精密 “齿轮组”,驱动着数值处理流程。编写函数求区间[100,500]中所有的回文数,要求每行打印10个数。根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码。如果操作数是浮点数,在 C 语言中是不允许直接进行。的结果是 -1,因为 -7 除以 3 商为 -2,余数为 -1;注意:每一个数据输出格式为 printf("%4d", i);的结果是 1,因为 7 除以 -3 商为 -2,余数为 1。取余运算要求两个操作数必须是整数类型,包括。开始你的任务吧,祝你成功!
59 1
|
4月前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
739 1
|
15天前
|
存储 算法 Java
JVM: 内存、类与垃圾
分代收集算法将内存分为新生代和老年代,分别使用不同的垃圾回收算法。新生代对象使用复制算法,老年代对象使用标记-清除或标记-整理算法。
19 3
|
3月前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。