当前课程知识点:C语言程序设计 >  第9章 指针 >  9.6 动态内存分配 >  动态内存分配

返回《C语言程序设计》慕课在线视频课程列表

动态内存分配在线视频

下一节:编译预处理

返回《C语言程序设计》慕课在线视频列表

动态内存分配课程教案、知识点、字幕

同学们好

这一节中我们将和同学们探讨

静态内存分配和动态内存分配

和大家一起研究动态内存分配的

四个函数malloc函数

calloc函数

realloc函数、free函数

为大家数据结构中

链表、栈、树和图的学习打下基础

同学们要多思考

多练习

静态内存分配

在编写一个C语言程序的过程中

如果要使用变量或数组必须先进行定义

然后才以使用

程序中定义变量或数组以后

系统就会给变量或数组按照

其数据类型及大小来分配相应的内存单元

这种内存分配方式称为静态内存分配

也就是说

这些内存在程序运 行前就分配好了

不可改变

静态内存分配一般是在

已知道数据量大小的情况下使用

比如说

要对10个学生的成 绩按降序输出

则可定义一个基类型为

整型的10个元素的数组

用于存放10个学生的成绩

然后再进行排序 动态内存分配

假设事先并不知道学生的具体人数

编写程序时

人数由用户输入

然后再输入学生的成绩

那又如何处理呢

能否像如下方式定义?

这种方式显然是错误的

因为数组定义时数组大小不能为变量

只能是整型常量或符号常量

也许可以这样来定义一个数组

将其定义得足够大

如: 使用define的符号常量方式

但这里又会存在一些问题

一是输入的学生数超过了1000怎么办?

因为你不知道到底输入的学生人数是多少

二是输入的学生数很小

假设是10

那么系统分配的1000个

整型单元只使用了10个

这就造成了内存单元的极大浪费

这就好像是吃饭分馒头

每人5个馒头

饭量大的不够吃

饭量小的造成浪费

那么有没有一种方法

使得在程序运行时来决定数组的大小呢?

C语言提供了动态内存分配

来解决这个问题

所谓动态内存分配是指在程序运行过程中

根据程序的实际需要来分配

一块大小合适的连续的内存单元

程序可以动态分配一个数组

也可以动态分配其他类型的数据单元

动态分配的内存需要有

一个指针变量记录内存的起始地址

下面介绍 ANSI C中常用的

几个动态内存分配函数

1)malloc( ) 函数

malloc

函数用于分配若干个字节的内存空间

返回一个指向该存储区地址的指针

如果系统不能提供足够的内存单元

函数将返回空指针(NUL)

其函数原型如下

其中需要说明如下两点

(1)size这个参数的含义是分配的内存的大小

以字节为单位

(2)用 malloc分配内存不一定成功

如果分配内存失败

则返回值是NULL(空指针)

如果成功

返回值则是一个指向空类型(void)的指针

即所分配内存块的首地址

void说明返回的指针所指向的内存块

可以是任何类型

如前面根据学生人数来建立数组的问题

可以通过调用函数 malloc

进行动态内存分配来解决

其方法如下

关于 malloc的使用需强调几点

(1) malloc前面必须要加上一个指针类型转换符

如上面的int *

因为malloc的返回值是空类型的指针

一般应与左边的指针变量类型一致

(2) malloc所带的一个参数是指

需分配的内存单元字节数

尽管可以直接用数字来表示

但一般写成如下形式

分配数量* 'sizeof(内存单元类型符)

如上面的n* sizeof(int)表示分配n个整型单元

如果我们把上面的

动态分配内存的语句改成如下形式

直接给出字节大小的方式

那么该语句在TC2.0或BC3.1

是没有任何间题的

与上面的动态分配语句是等价的

因为每个整型单元占2个字节

总共需分配2*n个字节

但在VC下则分配的内存单元就会少一半

因为VC下

每个int内存单元占4个字节

因此总共需分配的内存单元数应为

4*n个字节

为了能让编写的C语言程序能

在不同的环境下正确运行

所以写成n*sizeof(int)更具有通用性

(3) malloc可能返回NULL

表示分配内存失败

因此一定要检查分配的内存指针是否为空

如果是空指针

则不能引用这个指针

否则会造成系统崩溃

所以在动态内存分配的语句的后面

一般紧跟一条语句以判断分配是否成功

如果不成功要打印出错信息

结束程序

传递错误代码给系统

实现错误陷阱

2)函数 calloc

函数 calloc用于

给若干个同一类型的数据项

分配连续的存储空间

其中每个数据项的长度单位为字节

通过调用函数 calloc

所分配的存储单元

系统将其自动置初值0

其函数原型为

其中需要说明如下两点

(1)num表示向系统申请的内存空间的数量

size表示申请的每个内存空间的字节数

(2)同样用calloc分配内存不一定成功

如果分配内存失败

将返回空指针(NULL)

如果成功将返回一个

void类型的连续存储空间的首地址

如前面根据学生人数来建立数组的问题

同样可以通过调用函数

calloc进行动态内存分配来解决

其方法如下

程序中表示系统

申请n个连续的int类型的存储单元

并用指针 pscore指向该连续存储单元的首地址

系统中申请的

总的存储单元字节数为n*sizEof(int)

显然用函数 calloc申请的存储单元

相当于一个一维数组

函数calloc第一个参数决定了

一维数组的大小

第二个参数决定了数组元素的类型

函数的返回值就是数组的首地址

3)函数 realloc

函数 realloc

用于改变原来分配的存储空间的大小

其函数原型为如图

该函数的功能是将指针p

所指向的存储空间的大小改为size个字节

如果分配内存失败

将返回空指针(NULL)

如果成功

将返回新分配的存储空间的首地址

该首地址与原来分配的首地址不一定相同

函数 realloc主要应用场合是

当先前通过动态内存分配的存储空间

因实际情况需要进行扩充或缩小时

就可以使用函数realloc来解决

其好处是原存储空间中的数据值能保持不变

例如有下列程序段则执行

p=(char*)realloc(p,6*sizeof(char))

后的结果示意图如下

4 .动态内存释放

在C语言中

函数内部定义的非静态存储类型的

局部变量当函数运行结束时

系统自动会将这些变量所占用的内存释放

但是在函数内部动态分配的内存

系统是不会自动释放的

必须使用释放内存的函数free来释放

如果程序只知道申请内存

用完了却不返还

很容易将内存耗尽

使程序最终无法运行

要知道计算机中最宝贵的资源就是内存

因此需要动态分配内存的程序一定要坚持

好借好还

再借不难的原则

释放动态内存的函数free其原型如图

其中block是分配的动态内存的首地址

一般为指向该内存块首地址的指针变量

这一节中我们将和同学们探讨了

静态内存分配和动态内存分配

和大家一起研究了动态内存分配

的四个函数malloc函数

calloc函数

realloc函数和free函数

为大家数据结构中链表的

创建打下基础

同学们可以多动手练习

达到动态分配内存

规划使用的目的

同学们

这次的课就讲到这里

我们下次课再见

C语言程序设计课程列表:

第1章 C语言程序设计预备知识

-计算思维与计算机

--计算思维与计算机

--计算思维与计算机

--计算思维和计算机

第2章 C语言程序设计基础

-2.1 程序设计语言的发展及其特点和应用

--程序设计语言的发展及其特点和应用

--程序设计语言的特点及发展

- 2.2 C语言程序的基本结构及编制C语言程序的基本步骤

-- C语言程序的基本结构及编制C语言程序的基本步骤

--C语言程序的结构和编制步骤

第3章 基本数据类型、运算符与表达式

-3.1 C语言的数据类型

--C语言的数据类型

--C语言的数据类型

-3.2 常量

--常量

--常量

-3.3 什么是变量

--什么是变量

--什么是变量

-3.4 如何进行算术运算

--如何进行算术运算

--如何进行算术运算

-3.5 赋值运算符和逗号运算符

--赋值运算符和逗号运算符

--赋值运算符和逗号运算符

-3.6 数据类型转换

--数据类型转换

--数据类型转换

第4章 基本输入输出和顺序程序设计

-4.1 格式化输出printf

--格式化输出printf

--格式化输出

-4.2 格式化输入scanf及字符数据的非格式化输入输出

--格式化输入scanf及字符数据的非格式化输入输出

--格式化输入

第5章 选择结构程序设计

-5.1 关系运算符和关系表达式

--关系运算符和关系表达式

--关系运算符和关系表达式

-5.2 逻辑运算符和逻辑表达式

--逻辑运算符和逻辑表达式

--逻辑运算符和逻辑表达式

-5.3 条件运算符和条件表达式

--条件运算符和条件表达式

--条件运算符和条件表达式

-5.4 if语句

--if语句

--if语句

-5.5 switch语句

--switch语句

--switch语句

第6章 循环结构程序设计

-6.1 while语句

--while语句

--while语句

--do-while语句

-6.2 for语句

--for语句

--for语句

-6.3 循环的嵌套

--循环的嵌套

--循环的嵌套

-6.4 break语句和continue语句

--break语句和continue语句

--break和continue语句

第7章 数组

-7.1 一维数组的定义和引用

--一维数组的定义和引用

--一维数组的定义和引用

-7.2 一维数组的赋值

--一维数组的赋值

--一维数组的赋值

-7.3 二维数组的定义和引用

--二维数组的定义和引用

--二维数组的定义和引用

-7.4 二维数组的赋值

--二维数组的赋值

--二维数组的赋值

-7.5 字符串的本质

--字符串的本质

--字符串的本质

-7.6 字符串操作的常用函数

--字符串操作的常用函数

--字符串常用函数

-7.7 字符串数组

--字符串数组

--字符串数组

第8章 函数

-8.1 函数概述

--函数概述

--函数概述

-8.2 有参函数

--有参函数

--有参函数

-8.3 函数参数的传递方式

--函数参数的传递形式

--函数参数的传递方式

-8.4 变量的作用域和生存期

--变量的作用域和生存期

--变量的作用域和生存期

-8.5 变量的存储类型

--变量的存储类型

--变量的存储类型

-8.6 函数的嵌套和递归调用

--函数的嵌套和递归调用

--函数的嵌套和递归调用

-8.7 函数的作用域与封装

--函数的作用域与封装

--函数的作用域与封装

第9章 指针

-9.1 指针变量的概念(上)

--指针变量的概念(上)

--指针变量的概念(上)

-9.2 指针变量的概念(下)

--指针变量的概念(下)

--指针变量的概念(下)

-9.3 指向一维数组的指针变量

--指向一维数组的指针变量

--指向一维数组的指针变量

-9.4 指向二维数组的指针变量(上)

--指向二维数组的指针变量

--指向二维数组的指针变量(上)

-9.5 指向二维数组的指针变量(下)

--指向二维数组的指针变量(下)

--指向二维数组的指针变量(下)

-9.6 动态内存分配

--动态内存分配

--动态内存分配

第10章 预处理命令

-10.1 编译预处理

--编译预处理

第11章 复杂数据类型

-11.1 用户自己建立数据类型

--用户自己建立数据类型

--用户自己建立数据类型

-11.2 定义结构体类型变量

--定义结构体类型变量

--定义结构体类型变量

-11.3 结构体变量的引用与初始化

--结构体变量的引用与初始化

-11.4 结构体数组

--结构体数组

--结构体数组

-11.5 指向结构体类型数据的指针

--指向结构体类型数据的指针

--指向结构体类型数据的指针

第12章 文件

-12.1 文件的基本概念和文件指针

--文件的基本概念和文件指针

--文件的基本概念和文件指针

-12,2 文件的打开和关闭

--文件的打开和关闭

--文件的打开和关闭

-12.3 文本文件读写

--文本文件读写

--文本文件读写

-12.4 二进制文件读写

--二进制文件读写

--二进制文件读写

动态内存分配笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。