动态内分配——C语言

简介: 动态内分配——C语言

目录

内存分布图

动态内存分配

malloc

free

calloc

realloc(调整动态内存开辟的大小)

动态分配的注意事项

内存分布图

1.png

动态内存分配

malloc

描述

C 库函数 void *malloc(size_t size) 分配所需的内存空间,并返回一个指向它的指针。声明

void *malloc(size_t size)

参数

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

返回值

该函数返回一个指针 ,指向已分配大小的内存。如果请求失败,则返回 NULL。

使用

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
  //像内存申请10个整形的空间
  int* p = (int*)malloc(10 * sizeof(int));
  int i = 0;
  //判断是否开辟成功
  if (p == NULL)
  {
    printf("%s\n", strerror(errno));
  }
  else
  {
    for (i = 0; i < 10; i++)
    {
      *(p + i) = i;
    }
    for (i = 0; i < 10; i++)
    {
      printf("%d", *(p + i));
    }
  }
  return 0;
}

free

描述

C 库函数 void free(void *ptr) 释放之前调用 calloc、malloc 或 realloc 所分配的内存空间。

声明

void free(void *ptr)

参数

  • ptr -- 指针指向一个要释放内存的内存块,该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。如果传递的参数是一个空指针,则不会执行任何动作。

返回值

该函数不返回任何值。

注释

free释放ptr指向的空间后,并不会把str置为NULL,要自行将其置为空指针。

使用

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
  //像内存申请10个整形的空间
  int* p = (int*)malloc(10 * sizeof(int));
  int i = 0;
  //判断是否开辟成功
  if (p == NULL)
  {
    printf("%s\n", strerror(errno));
  }
  else
  {
    for (i = 0; i < 10; i++)
    {
      *(p + i) = i;
    }
    for (i = 0; i < 10; i++)
    {
      printf("%d", *(p + i));
    }
    //当动态申请的空间不再使用的时候
    //就应该还给操作系统
    free(p);
    p = NULL;
  }
  return 0;
}

calloc

描述

C 库函数 void *calloc(size_t nitems, size_t size) 分配所需的内存空间,并返回一个指向它的指针。malloc 和 calloc 之间的不同点是,malloc 不会设置内存为零,而 calloc 会设置分配的内存为零。

声明

void *calloc(size_t nitems, size_t size)

参数

  • nitems -- 要被分配的元素个数。
  • size -- 元素的大小。

返回值

该函数返回一个指针,指向已分配的内存。如果请求失败,则返回 NULL。

使用

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
  //像内存申请10个整形的空间
  int* p = (int*)calloc(10, sizeof(int));
  int i = 0;
  //判断是否开辟成功
  if (p == NULL)
  {
    printf("%s\n", strerror(errno));
  }
  else
  {
    for (i = 0; i < 10; i++)
    {
      *(p + i) = i;
    }
    for (i = 0; i < 10; i++)
    {
      printf("%d", *(p + i));
    }
    //当动态申请的空间不再使用的时候
    //就应该还给操作系统
    free(p);
    p = NULL;
  }
  return 0;
}

注释:会将元素初始化为零

realloc(调整动态内存开辟的大小)

让动态内存的开辟变得更加灵活

描述

C 库函数 void *realloc(void *ptr, size_t size) 尝试重新调整之前调用 malloccalloc 所分配的 ptr 所指向的内存块的大小.

声明

void *realloc(void *ptr, size_t size)

参数

  • ptr -- 指针指向一个要重新分配内存的内存块,该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。如果为空指针,则会分配一个新的内存块,且函数返回一个指向它的指针。
  • size -- 内存块的新的大小,以字节为单位。如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被释放,并返回一个空指针。

返回值

该函数返回一个指针 ,指向重新分配大小的内存。如果请求失败,则返回 NULL。

用法:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
  //像内存申请5个整形的空间
  int* p = (int*)malloc(5*sizeof(int));
  int i = 0;
  //判断是否开辟成功
  if (p == NULL)
  {
    printf("%s\n", strerror(errno));
  }
  else
  {
    for (i = 0; i < 5; i++)
    {
      *(p + i) = i;
    }
//在使用malloc开辟的20个字节空间
//       假设这里二十个字节不能满足我们的使用
//       希望我们能够有四十字节个空间
// 
    int* ptr = realloc(p, 40);
    if (ptr != NULL)
    {
      p = ptr;
    }
    for (i = 5; i < 10; i++)
    {
      *(p + i) = i;
    }
    //当动态申请的空间不再使用的时候
    //就应该还给操作系统
    free(p);
    p = NULL;
  }
  return 0;
}

注意:


1.原有的空间之后有足够大的空间,会在原本的空间后进行拓展开辟。


2.原有的空间之后没有足够大的空间,会重新开辟一段空间,将之前内容进行复制,然后将原有的空间进行释放。


3.malloc函数的返回的是无类型指针,在使用时一定要强制转换为所需要的类型。

4.重点:在使用malloc开辟空间时,使用完成一定要释放空间,如果不释放会造内存泄漏。

5.在使用malloc函数开辟的空间中,不要进行指针的移动,因为一旦移动之后可能出现申请的空间和释放空间大小的不匹配(eg:p++)

动态分配的注意事项

1.对NULL解引用操作


(在开辟空间时,可能开辟不成功就会返回空指针,因此在开辟后对其进行判断)


2.对动态开辟内存的越界访问。


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


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


(指针位置不能发生移动)


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


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


相关文章
|
7月前
|
存储 程序员 编译器
在C语言中.如何正确地分配和释放内存docx
在C语言中.如何正确地分配和释放内存docx
53 1
|
程序员 C语言
c语言:通讯录管理系统(动态分配内存版)
c语言:通讯录管理系统(动态分配内存版)
58 0
c语言:通讯录管理系统(动态分配内存版)
|
3月前
|
存储 C语言 C++
数据结构基础详解(C语言) 顺序表:顺序表静态分配和动态分配增删改查基本操作的基本介绍及c语言代码实现
本文介绍了顺序表的定义及其在C/C++中的实现方法。顺序表通过连续存储空间实现线性表,使逻辑上相邻的元素在物理位置上也相邻。文章详细描述了静态分配与动态分配两种方式下的顺序表定义、初始化、插入、删除、查找等基本操作,并提供了具体代码示例。静态分配方式下顺序表的长度固定,而动态分配则可根据需求调整大小。此外,还总结了顺序表的优点,如随机访问效率高、存储密度大,以及缺点,如扩展不便和插入删除操作成本高等特点。
215 5
|
C语言
C语言实现通讯录--动态版
C语言实现通讯录--动态版
53 0
|
7月前
|
C语言
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(二)
我们可以通过创建并定义符号常量NUMBER,来作为判断是否胜利的标准。如三子棋中,令NUMBER为3,则这八个方向中有任意一个方向达成3子连珠,则连珠的这个棋子所代表的玩家获胜。
74 1
|
7月前
|
算法 C语言 C++
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(一)
三子棋游戏设计的核心是对二维数组的把握和运用。
86 1
|
7月前
|
程序员 编译器 C语言
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free(下)
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free
45 0
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free(下)
|
7月前
|
编译器 数据库 C语言
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free(上)
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free
49 0
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free(上)
|
7月前
|
存储 C语言
动态+静态+文件操作 C语言实现通讯录
通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址
38 0
|
7月前
|
存储 编译器 C语言
C语言进阶⑱(文件上篇)(动态通讯录写入文件)(文件指针+IO流+八个输入输出函数)fopen+fclose(下)
C语言进阶⑱(文件上篇)(动态通讯录写入文件)(文件指针+IO流+八个输入输出函数)fopen+fclose
50 0