首页 > 系统相关 >C语言——动态内存分配

C语言——动态内存分配

时间:2024-04-07 21:30:12浏览次数:15  
标签:malloc 函数 int void free C语言 内存 动态内存 分配

在学习动态开辟内存之前,我们已经掌握了两种内存分配的方法:

int a = 10;
int arr[10] = { 0 };

这两种开辟空间方法的特点:

1.开辟空间的大小是固定的

2.数组在申明时,必须指定数组的长度,它所需要的内存在编译时分配

但有时,我们需要的内存大小在程序运行时才能知道,上述的两种方法就不能满足我们的需求了,所以,需要使用动态内存分配的方法来开辟内存

接下来介绍几个动态内存函数:

malloc函数

需包含头文件#include<stdlib.h>

void* malloc(size_t size);

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

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

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

如果函数参数size为0,malloc的行为属于标准未定义

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

free函数

需包含头文件#include<stdlib.h>

void free(void* ptr);

 free函数用来释放动态开辟的内存空间

  • 如果参数ptr指向的空间不是动态开辟的,那么free函数的行为是未定义的
  • 如果参数ptr指向的是NULL,那么函数什么都不做

calloc函数

需包含头文件#include<stdlib.h>

void* calloc(size_t num,size_t size);

该函数的功能是为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0

calloc与malloc的区别:

calloc函数会在返回地址之前把申请的空间的每个字节初始化为全0

realloc函数

需包含头文件#include<stdlib.h>

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

ptr 是要调整的内存地址

size 是调整后的大小

返回值为调整之后的内存的起始地址 

realloc函数的出现会让动态内存管理更加灵活,它可以做到对动态开辟内存大小的调整

realloc函数在调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间

realloc在调整内存空间时会遇到两种情况:

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

当为情况二时:在堆空间上另外找一个大小合适的连续空间来使用,将旧的空间中的数据拷贝到新的空间,在释放掉旧的空间后返回新空间的起始地址。

常见的动态内存错误

1. 对NULL指针的解引用操作

void test()
{
   int* p = (int *)malloc(INT_MAX/4);
   *p  = 20;  //如果p的值是NULL就会出现问题
   free(p);
}

2. 对动态开辟空间的越界访问

void test()
{
   int i = 0;
   int* p = (int *)malloc(10 * sizeof(int));
   if(NULL == p)
       exit(EXIT_FAILURE);
   for(i = 0; i <= 10; i++)
   {
       *(p+i) = i; //当i是10的时候越界访问
   }
   free(p);
}

 3. 对非动态开辟的内存使用free函数释放

void test()
{
   int a = 10;
   int *p = &a;
   free(p);
}

4. 使用free释放一块动态开辟内存的一部分

void test()
{
   int *p = (int *)malloc(100);
   p++;
   free(p);//p不再指向动态内存的起始位置
}

5. 对同一块空间多次释放

void test()
{
   int *p = (int *)malloc(100);
   free(p);
   free(p);//重复释放
}

6. 动态开辟内存忘记释放(内存泄漏)

void test()
{
   int *p = (int *)malloc(100);
   if(NULL != p)
   {
       *p = 20;
   }
}

int main()
{
   test();
   while(1);
}

!!!注意!!!动态开辟的空间一定要释放,并且要正确释放

 柔性数组

在C99中,结构体中最后一个成员允许是未知大小的数组,这就叫做柔性数组成员

typedef struct st_type
{
   int i;
   int a[];//柔性数组成员
}st-type;

柔性数组的特点

  1. 结构中柔性成员前面必须至少有一个其他成员
  2. sizeof 返回的这种结构大小不包括柔性数组的内存
  3. 包含柔性数组成员的结构用malloc函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小

柔性数组的好处

  1. 方便释放内存
  2. 有利于提高访问速度,减少内存碎片

标签:malloc,函数,int,void,free,C语言,内存,动态内存,分配
From: https://blog.csdn.net/m0_64005051/article/details/137326942

相关文章

  • C语言06-数组、函数
    第10章数组10.1数组的概念①数组四要素(1)数组名:本质上是一个标识符常量,命名需要符合标识符规范。(2)元素:同一个数组中的元素必须是相同的数据类型。(3)下标(索引、角标):从0开始的连续数字。(4)数组的长度:表示元素的个数。②C语言数组特点(不用记)(1)创建数组时会在内存中开辟......
  • 【C语言】文件操作(打开,关闭,写入,读取,指针位置)
    文件操作的函数在标准库stdio.h中。#include<stdio.h>1、fopen,fclose 打开文件,关闭文件fopen:打开文件。fclose:关闭文件。补充:perror:输出errno对应的错误信息。fopen:  FILE *fopen(constchar*filename,constchar*mode)参数:filename是字符串(要打开的文......
  • 【C语言】内存分区
    【C语言】内存分区文章目录【C语言】内存分区一、数据类型数据类型概念typedefvoid数据类型sizeof操作符总结二、变量变量的概念变量的修改方式三、程序内存分区模型内存分区栈区堆区全局/静态区常量区四、函数调用模型宏函数函数调用流程调用惯例函数变量传递分析......
  • 【C语言】贪吃蛇
    【C语言】贪吃蛇文章目录【C语言】贪吃蛇前言模块描述效果展示完整代码代码拆分定义蛇对象定义食物对象初始化蛇对象食物的初始化修改控制台光标位置画蛇和食物蛇移动控制基础知识游戏控制逻辑实现,接收键盘输入蛇的移动控制画墙设置光标不可见加速和显示成绩总结前......
  • 每日一题:C语言经典例题之小球蹦蹦跳跳
    题目描述调皮的小明将皮球从100m的高度自由落下,每次落地后反弹回原高度的一半,再落下,再反弹。求它在第N次落地时,共经过了多少米,第N次反弹多高。输入一个正整数N,表示球落地的次数。输出 length=球第N次落地时所经过了距离high=球第N次落地反弹的高度小数点后保留4位......
  • C语言文件操作
    本篇文章从文件是什么,为什么使用文件,到怎么使用文件来介绍文件。一.文件是什么?磁盘(硬盘)上的文件是文件。但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)。1.文件名文件名包含3部分:文件路径+文件名主干+文件按后缀。2.程序文件程序......
  • C语言游戏实战(11):贪吃蛇大作战(多人对战)
         成果展示:贪吃蛇(多人对战) 前言:这款贪吃蛇大作战是一款多人游戏,玩家需要控制一条蛇在地图上移动,吞噬其他蛇或者食物来增大自己的蛇身长度和宽度。本游戏使用C语言和easyx图形库编写,旨在帮助初学者了解游戏开发的基本概念和技巧。在开始编写代码之前,我们需要先......
  • C语言05-(跳转控制语句、断点调试)
    8.3跳转控制语句①break在switchcase结构中使用:跳出所在的case在循环结构(dowhile、while、for)中使用:跳出整个循环,循环结束注:跳出所在的循环!②continue在循环结构(dowhile、while、for)中使用:跳出本次循环,下次继续注:跳出所在的循环!③goto1.使用goto......
  • c语言程序实验————实验报告四
    c语言程序实验————实验报告四实验项目名称:实验报告2数据描述实验项目类型:验证性实验日期:2024年3月21日一、实验目的1.在熟练掌握if语句和switch语句的基础上,能灵活使用if语句和switch语句进行选择结构的程序设计2.学习调试程序二、实验硬、软件环境Windows计......
  • 操作系统综合题之“采用动态分区分配算法下的3种算法(首次适应算法、循环首次适应算法
    一、问题:当空闲链如下图,第一个空闲分区起始地址为20KB,大小为120KB;第二个空闲分区起始地址为200KB,大小为100KB;第三个空闲分区起始地址为400KB,大小为60KB。若某进程P1先申请大小为30KB的内存空间,随后进程P2再申请大小为20KB的内存空间,画出给P1分配完之后的空闲链和给P2分配完......