什么是内存的动态分配
还记得我们之前讲过的全局变量和局部变量吗?全局变量是分配在内存中的静态存储区的,非静态的局部变量(包括形参)都是分配在内存的动态存储区的。我们称上面的存储区为 栈 (stack)
。
除此之外,C 语言还允许建立内存动态分配区域,存放一些临时用的数据,这些数据:
- 不必在程序的声明部分定义;
- 不必等到函数结束时才释放;
- 需要时开辟,不需要时随时释放;
这些数据是临时存放在一个特别的自由存储区,称之为堆 ( haap)
。
我们可以根据需要,随时向系统申请所需大小的空间,但是我们没有声明
他们是变量还是数组,也没有名字
,所以我们只能通过指针来引用这些数据
。
建立内存的动态分配
清楚了什么是动态分配之后呢,我们来看看如何建立这么一个叫做堆
的区域。
我们对内存的动态分配,主要是通过系统功能提供的库函数来实现的,主要有malloc , calloc , free , realloc
这4个。
malloc 函数
函数原型:
void * malloc( unsigned int size);
malloc 的作用是在内存的动态存储区域分配一个长度为 size 的连续空间
。
形参 size 表示为无符号整型(unsigned),即不能为负数
。
此函数的返回值是所分配区域的第一个字节的地址
。
因为此函数是一个指针型函数,返回的是一组地址,地址是该分配区域的开头位置。
1 | malloc (100); //分配一个100字节长度的连续空间,函数值为该空间第1个字节的地址 |
这个指针的基类型是 void,即这个指针不指向任何类型的数据,只提供一个地址。如果执行失败(内存空间不足)则返回空指针。
注意
这里的函数是一个基类型为 void 的指针函数,void 的意思是这个指针函数的指针不指向任何数值,只返回一个地址。
这里的 void 不是函数返回值的类型,是只该指针函数的指针指向的数据的类型。切记!
calloc 函数
函数原型:
void * calloc(unsigned n , unsigned size);
calloc 的作用
是在内存的动态存储区域中分配 n 个长度为 size 的连续空间
,这个空间一般比较大
,足以保存一个数组。
用 calloc 函数可以为一维数组开辟动态存储空间
,n 为数组元素个数,每个元素长度为size。这就是动态数组。
这个指针的基类型是 void,即这个指针不指向任何类型的数据,只提供一个地址。如果执行失败(内存空间不足)则返回空指针。
1 | p=calloc(50,4); //开辟一个50X4个字节的临时分配域,把起始地址赋给指针变量 p。 |
free 函数
其函数原型为:
void free (void *p);
free 的作用是释放指针变量 p 所指向的动态空间,使这部分空间能重新被其它变量使用。
1 | free(p); //p 应该是最近一次调用calloc 或 malloc 函数时得到的函数返回值 |
free 无返回值。
realloc 函数
函数原型:
void realloc (void p, unsigned int size);
realloc 函数的作用
是,如果通过 malloc 或者 calloc 函数获得了动态空间
,想改变其大小
,可以用 realloc 重新分配
。
1 | realloc(p,50); //重新将指针 p 所指向的已分配的动态空间改为50字节 |
注意
以上的 4 个库函数在 stdlib.h 头文件中,需要使用时,需要使用 #include <stdlib.h>
引入到程序中。
Void 指针类型
上面我们操作内存动态分配的函数,都是基类型为 void 的指针。即我们可以定义一个基类型为 void 的指针
变量,它不指向任何类型的数据
。
请注意,不要把 void 理解为可以指向任何类型的数据,void 表示的是
不指向任何类型的数据
。
举一些例子
1 | int a=3; // 定义了一个整型变量a,并赋值为3 |
如果吧:
1 | void *p3=&a; //这里p3会获得 a 的纯地址,但并不指向a |
综合例子
1 |
|
声明空间并转换称为指定类型空间。
1 | p=(int *)malloc(3*sizeof(int)); |
因为我们声明的这些空间是要存放 int 型数据的
所以,我们使用 sizeof(int) 先获取了一下系统中整数的字节数,因为是 3 个学生的成绩,所以乘以了3。
我们知道 malloc 获取的空间是没有指向任何类型的,所以我们要把这段空间转换为 int 型,就在前面加一个 (int ) 表示转换指针类型为 int 型。
可以这么理解,要把指针转换成什么类型,就:
(类型名 *) 指针名
尾巴
这是我的个人学习笔记,主要是应付考研复习使用,充斥着一些吐槽和个人观点,并不严谨,欢迎大家参考、指正。