我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C语言深入讲解动态内存分配函数的使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C语言深入讲解动态内存分配函数的使用

局部变量和函数的形参向栈区申请空间

全局变量和static静态变量向静态区申请空间

动态内存分配向堆区申请空间(位于<stdlib.h>或<cstdlib>头文件)

一、malloc

void* malloc (size_t size);

分配内存块

分配一个连续可用的字节内存块,返回指向该内存块开头的指针。

新分配的内存块的内容未初始化,内存块中的数据为不确定值。

如果为参数为零,则返回值取决于特定的库实现(它可能是空指针,也可能不是空指针)。

参数

内存块的大小,以字节为单位。

是无符号整数类型,size_t。

返回值

成功时,为指向函数分配的内存块的指针。

此指针的类型始终为void*,可以将其转换为所需的数据指针类型。(C++由于其类型检查更为严格,则必须进行强制类型转换)

如果函数未能分配请求的内存块,则返回空指针NULL。

#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<stdio.h>
int main()
{
    int* p = (int*)malloc(10 * sizeof(int));
    if (p == NULL)
    {
        printf("%s\n", strerror(errno));
    }
    else
    {
        for (int i = 0; i < 10; ++i)
        {
            *(p + i) = i;
        }
        for (int i = 0; i < 10; ++i)
        {
            printf("%d ", *(p + i));
        }
    }
    free(p);
    p = NULL;
    
    return 0;
}

输出

0 1 2 3 4 5 6 7 8 9

二、free(用于释放动态开辟的空间)

void free(void* ptr);

解除分配内存块

1.若参数ptr指向的空间不是动态开辟的,那么free函数的行为是未定义的。

2.若参数ptr是NULL指针,则free函数什么也不做。

3.free只释放堆区空间,但ptr仍指向那块空间。所以使用完free后要将ptr置为NULL,切断ptr与该内存块的联系。

参数

指向要释放的那块空间的指针(必须指向初始位置)

返回值

错误案例

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int* p = (int*)malloc(sizeof(int) * 10);
    if (p == NULL)
    {
        return 1;
    }
    for (int i = 0; i < 10; ++i)
    {
        *(p + i) = i;
    }
    for (int i = 0; i < 10; ++i)
    {
        printf("%d ", *(p++));//这里指针移动
    }
    free(p);//导致free释放的不是初始位置的指针,程序崩溃
    p = NULL;
    return 0;
}

三、calloc

void* calloc(size_t num,size_t num);

分配和零初始化内存块

1.函数的功能是为num个大小为size的元素开辟空间。

2.与malloc的区别只在于calloc会在返回地址前将申请的空间的每个字母初始化为0。

#include <stdio.h>      
#include <stdlib.h>     
int main ()
{
  int i,n;
  int * pData;
  printf ("Amount of numbers to be entered: ");
  scanf ("%d",&i);
  pData = (int*) calloc (i,sizeof(int));
  if (pData==NULL) exit (1);
  for (n=0;n<i;n++)
  {
    printf ("Enter number #%d: ",n+1);
    scanf ("%d",&pData[n]);
  }
  printf ("You have entered: ");
  for (n=0;n<i;n++) printf ("%d ",pData[n]);
  free (pData);
  return 0;
}

四、realloc

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

重新分配内存块

1.ptr为要调整的内存空间,size为调整后的新大小

2.返回值为调整后的内存块的起始位置

注意事项

1.若ptr指向的空间之后有足够的空间可以追加,则直接追加,然后返回ptr。

2.若ptr指向的空间之后没有足够的内存空间,则realloc函数会重新找一块内存空间,开辟一块满足需求的内存空间,并且把原来内存中的数据拷贝过来,释放旧的内存空间,最后返回新开辟的内存空间的地址。

#include <stdio.h>      
#include <stdlib.h>     
int main ()
{
  int input,n;
  int count = 0;
  int* numbers = NULL;
  int* more_numbers = NULL;
  do {
     printf ("Enter an integer value (0 to end): ");
     scanf ("%d", &input);
     count++;
 
     more_numbers = (int*) realloc (numbers, count * sizeof(int));
 
     if (more_numbers!=NULL) {
       numbers=more_numbers;
       numbers[count-1]=input;
     }
     else {
       free (numbers);
       puts ("Error (re)allocating memory");
       exit (1);
     }
  } while (input!=0);
  printf ("Numbers entered: ");
  for (n=0;n<count;n++) printf ("%d ",numbers[n]);
  free (numbers);
  return 0;
}

五、常见的动态内存分配错误

1.对NULL指针的解引用操作(要进行返回值的判断)

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

3.对非动态开辟内存的空间的使用free进行释放

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

(若指针位置发生变化,归位后再进行释放)

5.对同一块动态内存的多次释放

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

六、柔性数组

C99中,结构体中的最后一个元素是未知大小的数组,被称为柔性数组成员。

特点

1.结构体中柔性数组成员前必须至少有一个其他成员。

2.sizeof返回的这种结构体的大小不包括柔性数组的内存大小。

3.包含柔性数组成员的结构体用malloc函数进行内存动态内存的动态分配,并且分配的内存应大于结构体的大小,以适应柔性数组的预期大小。

优势

1.方便内存释放。

2.利于访问速度,减少内存碎片。

#include<stdio.h>
#include<stdlib.h>
struct S
{
    int n;
    int arr[];
};
int main()
{
    struct S* ps = (struct S*)malloc(sizeof(struct S) + 5 * sizeof(int));
    //给arr分配内存20个字节的空间
    if (ps == NULL)
    {
        return 1;
    }
    //……………………操作
    free(ps);
    ps = NULL;
    return 0;
}

到此这篇关于C语言深入讲解动态内存分配函数的使用的文章就介绍到这了,更多相关C语言动态内存分配内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C语言深入讲解动态内存分配函数的使用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C语言动态内存分配图文讲解

给数组分配多大的空间?你是否和初学C时的我一样,有过这样的疑问。这一期就来聊一聊动态内存的分配,读完这篇文章,你可能对内存的分配有一个更好的理解
2023-01-17

C语言动态内存分配函数如何使用

这篇文章主要介绍“C语言动态内存分配函数如何使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C语言动态内存分配函数如何使用”文章能帮助大家解决问题。局部变量和函数的形参向栈区申请空间全局变量和st
2023-06-30

C语言动态内存分配怎么使用

这篇文章主要介绍了C语言动态内存分配怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言动态内存分配怎么使用文章都会有所收获,下面我们一起来看看吧。一、动态内存分配的意义C语言中的一切操作都是基于内存的
2023-06-30

C语言的动态内存如何分配

今天小编给大家分享一下C语言的动态内存如何分配的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。动态内存分配的定义首先我们要搞清
2023-07-02

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录