问题引入:我们在定义一个变量时,计算机是如何存取该变量的呢?如下代码,计算机是如何存入和读取a的值的呢?
#include<stdio.h>
int main(void)
{
int a;
scanf("%d", &a);
printf("%d",a);
return 0;
}
其实,我们在程序中定义一个变量,系统并不认识这个字母。原来,变量名称要被编译器转化为内存地址(这个内存地址编译器知道,而程序员不知道)。当我们读取这个变量,实际上是找到这个变量名所对应的地址,然后读取其中的值。
变量在使用前必须被定义且安排好存储空间。全局变量,静态局部变量的存储空间是在编译时确定,在程序开始执行前完成。函数参数,局部变量是在执行函数或者进入变量定义所在的复合语句时为他们分配存储空间的。
但是,例如在程序中定义一个数组,常常很难为数组估计合适的大小。理想的做法是在程序运行时再确定数组的实际大小。
那么,c语言支持在程序运行期间动态分配内存吗?如果能,又是如何分配的呢?
答:c语言支持程序运行期间动态分配内存,而这一功能只能通过指针来实现。
在此,我们先来理解两个概念,即堆栈的概念。在程序运行期间,存放函数的参数值,局部变量的内存区域由系统自动分配和释放,称为栈。而由程序员分配释放的内存区域称为堆。也就是说堆和栈并非在一起,堆是由程序员可操作的,而栈由系统控制的。在分配堆上的内存时,由程序员跟踪所分配的内存,如果该内存不再需要,应及时释放这些空间,以便以后重用它们。
回到前面,我们说在程序中定义一个数组,常常很难为数组估计合适的内存大小,那么在程序运行期间如何为它分配合适的内存大小?
任务驱动:如何为一个数组动态分配内存?
函数:使用动态内存分配最简单的标准库函数是malloc()。//此函数在使用时需要包含头文件<stdlib.h>。malloc()函数的原型如下:void *malloc(unsigned size)
在此我们来解释一下上述malloc函数原型:该函数返回一个指向void类型的指针,它是可以表示任何指针类型的通用指针。void类型的指针可以和其它任何类型的指针相互赋值,都无需使用字符转换运算符。但是指向void类型的指针不能间接寻址运算,因为void类型的指针只能是简单地包含一个未知数据类型的首地址,该如何理解该地址的内容对编译器而言是未知的。即本质上void 类型的指针本质上只是内存地址,可以包含任何类型对象的地址。void*常用作形式参数类型,可以接受任何类型的实参指针。此处由于malloc()函数无法知道计划存储在内存块中的数据类型是什么类型,所以不能返回int类型,char类型的普通类型的指针。
函数功能:在内存的动态存储区中分配长度为size的内存空间。//若申请成功,则返回一个指向所分配的内存空间的起始地址的指针;若申请不成功,则返回NULL(值为0)。
int *p = (int *)malloc(100);
上述程序中,malloc(100)表示size的值为100,即将分配100个字节的内存块,malloc(100)返回该内存块的首地址,并把这个内存块的首地址转化为int*类型,赋给指针变量p, p指向第一个整数的位置。如果一个整数占4个字节,这个内存块可以放25个整数。(但是如果某机器int类型的长度大于4个字节,则该内存块可以存储的整数个数小于预期,可能导致系统越组访问,导致系统崩溃等异常行为。所以,申请内存时一定要使用sizeof运算符获取当前系统int类型所需内存空间)。
如何完成申请n个int类型数据的内存块?
int *p = (int *)malloc(n * sizeof(int))
注:因为数组和指针的密切关系,一旦p指向某内存块的首元素,就不能忽略p是指针这一事实,可以将其用作数组的名称。例如:
int *p = (int *)malloc(n * sizeof(int))
for (i = 0; i < n; i++)
p[i] = i;
现在,我们已经完成了数组内存动态分配的任务,那么一个数组的内存动态分配完成以后,如何释放动态分配的内存呢?
在动态分配内存时,应该在不需要该内存时将内存释放。如果频繁申请内存而没有及时释放不再需要的内存,可能会将内存耗尽。
任务驱动:释放内存
函数:free()函数 //free函数用来释放不再需要的内存,其原型为void free(void *ptr);
free形参是*void类型,所以任何类型的指针都可以作实参传递给这个函数,但要求这个实参必须是先前由动态分配函数返回的指针。
操作:free(p)//要释放动态分配的内存,该内存的地址存储再指针p中。
下面我们通过一个习题来巩固上述知识:
先输入一个正整数n,再输入任意n个整数,然后逆序输出这n个整数。要求:使用动态内存分配为这n个整数分配空间。
//动态申请一个一维数组
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int n, i, *p;
printf("请输入元素个数:");
scanf("%d", &n);
p = (int *)malloc(n * sizeof(int));//申请存储n个int型数据的内存空间
for(i = 0; i < n; i++)
scanf("%d", p+i);
for(i = n - 1; i >= 0; i--)
printf("%d", p[i]);
printf("\n");
free(p);
return 0;
}