C语言中,在声明数组时,必须明确告诉编译器数组的大小,之后编译器就会在内存中为该数组开辟固定大小的内存。有些时候,用户并不确定需要多大的内存,使用多大的数组,为了保险起见,有的用户采用定义一个大数组的方法,开辟的数组大小可能比实际所需大几倍甚至十几倍,这造成了内存的浪费,带来了极大的不便。另一方面,即使用户确切知道要存放的元素个数,但随着问题的深入,元素数目可能会变化,变少还好处理,可如果数目增加呢,用什么来存储的,类似于数组内存这种分配机制就称为静态分配,很明显,静态分配是由编译器完成的,在程序执行前便已指定。显而易见,静态分配虽然直观,易理解,但存在明显的缺陷,不是容易浪费内存就是内存不够用,为解决这一问题,C语言引入了动态分配机制。
C语言函数库中提供了malloc和free函数,允许用户用户调用以动态申请说需要的内存,给程序的设计带来了很大的灵活性。(引用尹成的ppt)
现在我们来创建一个动态大小的数组
#include<stdio.h> #include<stdlib.h> //内存释放完成以后必须释放 //分配动态数组 void main(){ int num = 10; int *p = malloc(num * sizeof(int)); printf("%x", p);//打印内存地址 for (int i = 0; i < num; i++) { printf(" %d", p[i] = i + 1); } //内存释放完成以后必须释放 free(p); system("pause"); }
#include<stdio.h> #include<stdlib.h> //内存释放完成以后必须释放 //分配动态数组 void main(){ //calloc需要两个参数以指定申请内存块的大小,第一个参数一种数据结构的个数,第二个参数是单个数据结构的大小。
//注意:malloc一般不会初始化系统分配的内存块,通常需要使用memset()函数来初始化,而calloc()函数会初始化系统分配的内存块,将所有的位(bit)置零。 //calloc一般使用后要使用 free(起始地址的指针) 对内存进行释放,不然内存申请过多会影响计算机的性能, //以至于得重启电脑。如果使用过后不清零,还可以使用指针对该块内存进行访问。 int *p = (int *)calloc(50,sizeof(int));//动态分配 for (int i = 0; i < 50; i++) { printf(" %d", p[i] = i + 2); } printf(" %x", p); printf("******************************* "); //realloc将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域 //(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。 //realloc会把释放的内存拷贝到新地址, //新的大小可大可小(但是要注意,如果新的大小小于原内存大小,可能会导致数据丢失,慎用!) int *p1 = realloc(p, sizeof(int)* 75); printf(" %x", p1); printf("******************************* "); for (int i = 0; i < 75; i++) { printf(" %d", p1[i]); } //当内存不再使用时,应使用free()函数将内存块释放。 free(p1); //通过最终结果观察可知,通过realloc函数在calloc函数的内存上所新分配的内存其实首地址是一样的, //即p的值和p1的值是一样的 //好像内存机制并不是复制calloc函数的内存,而是在calloc函数的内存的基础上又申请了一段 system("pause"); }