标题：C语言动态数组
词目释义
动态数组，是相对于静态数组而言。静态数组的长度是预先定义好的，在整个程序中，一旦给定大小后就无法改变。而动态数组则不然，它可以随程序需要而重新指定大小。动态数组的内存空间是从堆（heap）上分配（即动态分配）的。是通过执行代码而为其分配存储空间。当程序执行到这些语句时，才为其分配。程序员自己负责释放内存。（欲详细了解堆请见堆栈）为什么要使用动态数组？在实际的编程中，往往会发生这种情况，即所需的内存空间取决于实际输入的数据，而无法预先确定。对于这种问题，用静态数组的办法很难解决。为了解决上述问题，C语言提供了一些内存管理函数，这些内存管理函数结合指针可以按需要动态地分配内存空间，来构建动态数组，也可把不再使用的空间回收待用，为有效地利用内存资源提供了手段。动态数组与静态数组的对比对于静态数组，其创建非常方便，使用完也无需释放，要引用也简单，但是创建后无法改变其大小是其致命弱点！ 
对于动态数组，其创建麻烦，使用完必须由程序员自己释放，否则严重会引起内存泄露。但其使用非常灵活，能根据程序需要动态分配大小。 
如何构建动态数组遵循原则申请的时候从外层往里层，逐层申请； 
释放的时候从里层往外层，逐层释放。 
构建所需指针
基础概念
C#集合、C#动态数组的概念之集合，什么是集合呢？集合就如同数组，用来存储和管理一组特定类型的数据对象，除了基本的数据处理功能，集合直接提供了各种数据结构及算法的实现，如队列、链表、排序等，可以让你轻易地完成复杂的数据操作。在使用数组和集合时要先加入system.collections命名空间，它提供了支持各种类型集合的接口及类。集合本身上也是一种类型，基本上可以将其作为用来存储一组数据对象的容器，由于c#面向对象的特性，管理数据对象的集合同样被实现成为对象，而存储在集合中的数据对象则被称为集合元素。这里提到了接口这个概念，它也是面向对象编程进化的重要标准，我们在这里不做过多的讲解，先注重学习集合中的对象及其使用就可以了，下面我们来学习第一种集合：
C#集合、C#动态数组的概念之C#动态数组ArrayList.ArrayList 类提供了继承了IList接口。什么是继承呢？这也是面向对象语言的重要特点之一，现在你们先把它理解为，如果一个对象继承了类或接口，那么它也具有了这个类和接口中的方法、属性，可以用这些继承的方法和属性来做相应的操作，比如：数组增加元素没有Add（）方法，但是动态数组ArrayList继承了一个增加元素有Add（）方法的接口，那么当它要增加元素的时候，不仅可以用索引，也可以用继承下来的Add（）方法了。随着学习的深入，我会给大家再具体讲解继承的概念和使用继承的好处。那么下面让我们来看看动态数组所继承的这个接口IList它有什么特性呢？
C#动态数组之 Ilist接口：定义了利用索引访问集合对象的方法，还继承了ICollection和IEnumerable接口，除实现了接口原有的方法成员外，其本身也定义多个专门的方法成员，例如新增、移除、在指定位置插入元素或是返回特定元素在集合中所在的位置索引，这些方法主要为集合对象提供类似数组的元素访问功能。
C#动态数组之ILsit接口成员：add、insert、RemoveAt、Remove、contains、Clear、indexof方法，它最大的特色在于提供类似数组索引的访问机制。
C#集合、C#动态数组的概念的基本情况就向你介绍到这里，希望对你了解和学习C#集合、C#动态数组的概念有所帮助。
必看知识
由于百科里贴的代码每行前都会有许多中文空格，造成直接复制粘贴到编译器上编译时会出现许多错误。（除非自己手工把代码前的空格全删掉）
所以我特地把代码贴到了扩展资料那，要的话去那拿吧。
构建实例
一维#include <stdio.h>
#include <stdlib.h>
int main()
{
int n1,i;
int *array;
puts("输入一维长度：");
scanf("%d",&n1);
array=(int*)malloc(n1*sizeof(int));//第一维
for(i=0;i<n1;i++)
{
array[i]=i+1;
printf("%d\t",array[i]);
}
free(array);//释放第一维指针
return 0;
}二维#include <stdlib.h>
#include <stdio.h>
int main()
{
int n1,n2;
int **array,i,j;
puts("输入一维长度:");
scanf("%d",&n1);
puts("输入二维长度:");
scanf("%d",&n2);
array=(int**)malloc(n1*sizeof(int*)); //第一维
for(i=0;i<n1; i++)
{
array[i]=(int*)malloc(n2* sizeof(int));//第二维 
for(j=0;j<n2;j++)
{
array[i][j]=i+j+1;
printf("%d\t",array[i][j]);
}
puts("");
}
for(i=0;i<n1;i++)
{
free(array[i]);//释放第二维指针
}
free(array);//释放第一维指针
return 0;
}三维#include <stdlib.h> 
#include <stdio.h>
int main()
{
int n1,n2,n3;
int ***array;
int i,j,k;
puts("输入一维长度:");
scanf("%d",&n1);
puts("输入二维长度:");
scanf("%d",&n2);
puts("输入三维长度:");
scanf("%d",&n3);
array=(int***)malloc(n1*sizeof(int**));//第一维 
for(i=0; i<n1; i++) 
{
array[i]=(int**)malloc(n2*sizeof(int*)); //第二维
for(j=0;j<n2;j++)
{
array[i][j]=(int*)malloc(n3*sizeof(int)); //第三维
for(k=0;k<n3;k++)
{
array[i][j][k]=i+j+k+1;
printf("%d\t",array[i][j][k]);
}
puts("");
}
puts("");
}
for(i=0;i<n1;i++)
{
for(j=0;j<n2;j++)
{
free(array[i][j]);//释放第三维指针
}
}
for(i=0;i<n1;i++)
{
free(array[i]);//释放第二维指针
}
free(array);//释放第一维指针
return 0;
}四维#include <stdlib.h> 
#include <stdio.h>
int main()
{
int n1,n2,n3,n4;
int ****array;
int i,j,k,m;
puts("输入一维长度:");
scanf("%d",&n1);
puts("输入二维长度:");
scanf("%d",&n2);
puts("输入三维长度:");
scanf("%d",&n3);
puts("输入四维长度:");
scanf("%d",&n4);
array=(int****)malloc(n1*sizeof(int***));//第一维 
for(i=0; i<n1; i++) 
{
array[i]=(int***)malloc(n2*sizeof(int**)); //第二维
for(j=0;j<n2;j++)
{
array[i][j]=(int**)malloc(n3*sizeof(int*)); //第三维
for(k=0;k<n3;k++)
{
array[i][j][k]=(int*)malloc(n4*sizeof(int));//第四维
for(m=0;m<n4;m++)
{
array[i][j][k][m]=i+j+k+m+1;
printf("%d\t",array[i][j][k][m]);
}
puts("");
}
puts("");
}
puts("");
}
for(i=0;i<n1;i++)
{
for(j=0;j<n2;j++)
{
for(k=0;k<n3;k++)
free(array[i][j][k]);//释放第四维指针
}
}
for(i=0;i<n1;i++)
{
for(j=0;j<n2;j++)
{
free(array[i][j]);//释放第三维指针
}
}
for(i=0;i<n1;i++)
{
free(array[i]);//释放第二维指针
}
free(array);//释放第一维指针
return 0;
}
数组案例
#include <stdio.h>
#include <stdlib.h>
int main()
{
int*n,*p;
int i;
n=(int*)calloc(1,sizeof(int));
for(i=0;i<5000;i++)
{
n[i]=i+1;
printf("%d\t",n[i]);
p=(int*)realloc(n,(i+2)*sizeof(int));//动态扩充数组
if(p!=NULL)
n=p;
else
{
puts("error!");
return 0;
}
}
free(n);
return 0;
}
游戏应用
预备知识（1）getch()
函数原型： int getch(void);
函数功能： 从控制台读取一个字符，但不显示在屏幕上。
函数返回： 读取的字符。
（2）rand()
函数原型: int rand(void); 
函数功能: 随机函数， 产生0到32767间的随机整数(0到0x7fff之间)。 
函数返回: 随机整数 
所属文件: <stdlib.h>
（3）srand()
函数原型: void srand(unsigned seed); 
函数功能: 该函数和rand随机函数配合使用，产生随机数的起始发生数据。 
参数说明: seed为无符号整数。 
所属文件: <stdlib.h>
（4）time()
函数原型: time_t time(time_t *timer) 
函数功能: 得到机器的日历时间或者设置日历时间。 
函数返回: 机器日历时间。 
参数说明: timer=NULL时得到机器日历时间，timer=时间数值时，用于设置日历时间，
time_t是一个long类型。 
所属文件: <time.h>
（5）'\b'实现退格，即当前光标后退一格。
（6）'\a'实现响铃，即执行时计算机会嘟一声。
（7）得到随机数值范围在a~b（包含b）的方法：rand()%(b-a+1)+a;
代码#include <stdio.h>
#include <conio.h>//getch()函数所需头文件
#include <stdlib.h>//随机函数所需头文件
#include <time.h>//time()函数所需头文件
void clear(void)//此函数用以清除当前行
{
printf("\r \r");
}
void start(void)
{
puts("这是消单词游戏的精简版，还不会图像编程的人可以看一看");
puts(" 由于没有引人数据库，所以此单词是模拟的。");
puts("按任意键开始,按Esc键结束,按tab键重新开始:");
puts(" 一旦输错，将发出声音警告，你必须重新输入。");
puts(" 按任意键开始,按Esc键结束:");
if( '\x1b' == getch() ) //按Esc键结束
{
exit( 1 );
}
}
int main()
{
char*c_rand,*c_input;
int i,j,N,n,space,N_rand;
start();
printf("\r你想消最多由多少个字母组成的单词？(输入数字(1-9)");
n=getch();
N=n-'0';//将输入的字符转换为整型数字
clear();//清除当前行
if(!((N>=1&&N<=9)||n==27))//27是键Esc的ASII值
{
printf("\r范围错误，请重新开始：");
getch();
exit(1);//异常退出
}
if(n==27)
return 0; 
srand(time(NULL));//用来对随机函数初始化
c_rand=(char*)malloc(N+1);
c_input=(char*)malloc(N+1);
while(1)
{
N_rand=rand()%N+1;//实现单词长度随机定义
for(i=0;i<N_rand;i++)
{
c_rand[i]=(rand() ==0)?(rand()&+'A'):(rand()&+'a');//随机取个字母
}
c_rand[N_rand]='\0';
//下面四行代码实现单词位置随机出现
space=rand() % 50;
putchar('\r');
for(i=0;i<space;i++)
putchar(' ');
printf("%s",c_rand);
for(i=0;i<N_rand;i++)
{
c_input[i]=getch();//用户输入
if(c_input[i]=='\x1b')//"\x1b"代表的是Esc键
break;
//下面五行代码实现字母消失效果
putchar('\r');
for(j=0;j<space;j++)
putchar(' ');
for(j=0;j<=i;j++)
putchar(' ');
if(c_input[i]!=c_rand[i])
{
i=-1;
putchar('\a');
//下面四行代码代码字母重现效果
putchar('\r');
for(j=0;j<space;j++)
putchar(' ');
printf("%s",c_rand);
}
}
if(c_input[i]=='\x1b')//"\x1b"代表的是Esc键
break;
}
free(c_rand);
free(c_input);
return 0; 
}