动态数组

数组是C语言中的很重要的一种构造类型,最初我们学习的都是静态数组,但是,静态数组有着自己难以改变的缺点——数组长度固定。

一般在静态数组定义后,系统就会为其分配对应长度的连续的专有内存空间,可是,我们都知道,不同的运行样例,所需要的数组长度是不一样的,为了所有样例都可以执行,一般我们会将数组长度设置为一个很大的值,比如:我一般都是借助宏定义直接声明1000,这个长度是可以满足我日常所需的。虽然这种方式,满足了一般运行的要求,但是它极大的浪费了内存。

于是我们引出了动态数组的概念,顾名思义,“动态”体现在数组长度可以由用户自己定义上。那么今天来总结一下,动态数组的两种实现方式。

方式1:C99变长数组

C99标准规定,我们可以通过变长数组的方式来实现动态数组,在我们程序中使用一个变量(非const值)从键盘上获取数组的长度。

//变长数组实现动态数组 
#include<stdio.h>
int main() {
	int n;
	printf("请输入数组的长度:"); 
	scanf("%d",&n);
	int sz[n];
	printf("请输入数组的元素:\n");
	for(int i=0; i<n; i++)
		scanf("%d",&sz[i]);
	printf("打印数组的元素:\n");
	for(int i=0; i<n; i++)
		printf("%d\t",sz[i]);
	return 0;
}

android 数组动态 动态数组类_数组

方式2:内存管理函数

C语言提供了一系列的内存管理函数来帮助我们来按需要动态的分配和回收内存空间。这恰恰就是动态数组另一种实现方式的基础,我们可以利用内存管理中的内存申请和释放函数,在程序的运行过程中进行数组长度的指定。

那么我们先来看一下动态数组中会涉及到的常用的内存管理函数。(涉及到的头文件是:<stdlib.h>)

(1)malloc()

  • 函数原型:
(类型说明符*) malloc(unsigned int size);
  • 功能:在内存的动态存储区中分配一块长度size字节的连续区域。

(2)calloc()

  • 函数原型:
(类型说明符*) calloc(n,size);

在这里,我们需要注意一下,

  • 功能:在内存的动态存储区中分配n块长度size字节的连续区域。

(3)realloc()

  • 函数原型:
(类型说明符*) realloc(void *p,int size);
  • 功能:重新分配堆上的void指针p(可以将void*理解为任意类型的指针变量类型)所指的空间,使其长度为size个字节,同时会复制原有内容到新分配的堆上存储空间。
    注意,size可大可小(如果新的大小大于原内存大小,则新分配部分不会被初始化;如果新的大小小于原内存大小,可能会导致数据丢失)

(4) free()

  • 函数原型:
void  free(void* p);
  • 功能:释放void * p所指的内存空间

注意:

在molloc,calloc,realloc三个函数中

①类型说明符是申请的地址将要存储的数据类型;

②函数的返回值代表申请空间是否成功,如果成功,返回申请到的空间的首地址,如果不成功,返回NULL(我们后续的操作建立在空间申请成功的基础上,所以我们需要在申请空间后,通过返回值判断空间是否申请成功);

③molloc,calloc两个函数的区别在于molloc申请的是一块size空间,而calloc可以指定申请的块数,即n块size空间。

使用代码来应用一下上面的几个函数。

//以一维数组为例,展示动态数组的建立
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
	int *arr=NULL,*new_arr=NULL,size,new_size;
	printf("请输入数组长度:");
	scanf("%d",&size);
//	arr=(int*)malloc(sizeof(int)*size);
	arr=(int*)calloc(size,sizeof(int));
	if(arr==NULL) {
		printf("内存申请失败!");
		exit(1);
	}
	printf("请输入数组元素:");
	for(int i=0; i<size; i++) {
		scanf("%d",&arr[i]);
	}
	printf("打印数组元素:\n");
	for(int i=0; i<size; i++)
		printf("%d\t",arr[i]);
	new_arr=(int*)realloc(arr,2*size*sizeof(int));
	printf("\n容量扩大为原来2倍,请输入数组元素:");
	for(int i=0; i<2*size; i++) {
		scanf("%d",&new_arr[i]);
	}
	printf("\n再次打印数组元素:\n");
	for(int i=0; i<2*size; i++)
		printf("%d\t",new_arr[i]);
	free(arr);
	return 0;
}

android 数组动态 动态数组类_动态数组_02


代码给出了一维数组的建立,其实二维数字也是类似的方法:先申请空间——>判断空间是否申请成功——>使用申请成功的空间——>free掉申请的空间。不过需要注意的是,二维数组的逐层申请和释放空间的顺序。在申请空间时,遵循由外向里的逐层申请次序;

在释放空间时,遵循由里向外的逐层释放次序。

android 数组动态 动态数组类_动态数组_03