36 动态分配内存与指向他的指针
点击蓝字
关注我们
DRAGON BOAT FESTIVAL
01 传统数组的缺点
“传统数组”就是前面所使用的数组,与动态内存分配相比,传统数组主要有以下几个缺点:
1) 数组的长度必须事先指定,而且只能是常量,不能是变量。比如像下面这么写就是对的:
int a[5];
而像下面这么写就是错的:
int length = 5;
int a[length]; //错误
2) 因为数组长度只能是常量,所以它的长度不能在函数运行的过程当中动态地扩充和缩小。
3) 对于数组所占内存空间程序员无法手动编程释放,只能在函数运行结束后由系统自动释放,所以在一个函数中定义的数组只能在该函数运行期间被其他函数使用。
而动态内存就不存在这个问题,因为动态内存是由程序员手动编程释的,所以想什么时候释放就什么时候释放。只要程序员不手动编程释放,就算函数运行结束,动态分配的内存空间也不会被释放,其他函数仍可继续使用它。除非是整个程序运行结束,这时系统为该程序分配的所有内存空间都会被释放。
所谓“传统数组”的问题,实际上就是静态内存的问题。我们讲传统数组的缺陷实际上就是以传统数组为例讲静态内存的缺陷。本质上讲的是以前所有的内存分配的缺陷。正因为它有这么多缺陷,所以动态内存就变得很重要。动态数组能很好地解决传统数组的这几个缺陷。
02 什么是内存的动态分配
全局变量是分配在内存中的静态存储区的,非静态的局部变量(包括形参)是分配在内存中的动态存储区的,这个存储区是一个“栈”的区域。
C语言允许建立内存动态分配区域,以存放一些临时用的数据,这些数据不必在程序的声明部分定义,也不必等到函数结束时才释放,而是需要时随时开辟,不需要时随时释放。这些数据是临时存放在一个特别的自由存储区,称为“堆”。
03 怎么建立内存的动态分配
malloc函数
函数原型:
void *malloc(unsigned int size);
其作用是在内存的动态存储区分配一个长度为size的连续空间。形参size的类型定为无符号整型。此函数是一个指针型函数,返回的指针指向该分配域的开头位置。
calloc函数
函数原型:
void *calloc(unsigned n,unsigned size);
其作用是在内存的动态存储区中分配n个长度为size的连续空间,这个空间一般比较大,足以保存一个数组。
free函数
函数原型:
void free(void *p);
其作用是释放指针变量p所指向的动态空间,使这部分空间能重新被其他变量使用。
realloc函数
函数原型:
void *realloc(void *p,unsigned int size);
如果已经通过malloc函数或者calloc函数获得了动态空间,想改变其大小,可以用realloc函数重新分配。
C99标准把意思malloc、calloc、realloc函数的基类型定为void类型,这种指针称为无类型指针。
04 void指针类型
指向void类型应该理解为指向空类型或者不指向确定的类型的数据。
把void指针赋值给不同基类型的指针变量时,编译系统会自动进行转换,不必用户自己进行强制转换。
内存的动态分配主要应用于建立程序中的动态数据结构中。
05 free函数的使用
定义一个指向动态内存的指针变量 p:
int *p = malloc(sizeof*p);
前面讲过,动态分配的内存空间是由程序员手动编程释放的。那么怎么释放呢?用 free 函数。
free 函数的原型是:
void free(void *p);
free 函数无返回值,它的功能是释放指针变量 p 所指向的内存单元。此时 p 所指向的那块内存单元将会被释放并还给操作系统,不再归它使用。操作系统可以重新将它分配给其他变量使用。
需要注意的是,释放并不是指清空内存空间,而是指将该内存空间标记为“可用”状态,使操作系统在分配内存时可以将它重新分配给其他变量使用。
指针变量 p 被释放之后,它仍然是指向那块内存空间的,只是那块内存空间已经不再属于它了而已。
球分享
球点赞
球在看