一、数组
1.1什么是数组
数组:相同数据类型的元素按一定顺序排列的集合,用数组进行编程可以快速有效地针对大量的数据进行处理,从而提高了效率。
1.2数组名的含义
所以的数组名都是指针常量,它保存着该数组首个元素的地址,因为为常量,所以诸如num++,num--等对数组名的运算都是不合法的。
二、一维数组与二维数组
2.1理解一维数组
(1)一维数组的定义:数据类型 数组名 [数组大小];(这里数组大小也可用宏代替,定义宏的好处在于有多个相同大小的数组定义时,当修改这些数组的大小只需修改宏定义,提高了代码质量),例如:int num[12];
(2)一维数组的初始化
①int a[10] = {0,1,2,3,4,5,6,7,8,9};//对所有元素赋初值
②int a[10] = {0,1,2,3,4};//对前几个元素赋初值,剩余的元素值为0
③int a[10] = {0};//使所有元素值为0
④int a[ ] = {0,1,2,3,4};//当对所以元素赋初值时可省去数组长度(已知数组元素总个数)
2.2一维数组的地址及数组名操作命令含义
(1)一维数组示意图
这里a为指针常量,它代表数组首元素a[0]的地址。
(2)&a、*(&a)与**(&a)操作命令的含义
&a:数组a的地址(对数组名取地址为该数组的地址);
*(&a):对一维数组a的地址取值,结果为数组a首元素的地址;
**(&a):数组a首元素的值
2.3理解二维数组
(1)二维数组的定义:数据类型 数组名 [常量表达式][常量表达式];
对于二维数组的理解,我们可以理解它的组成元素是一维数组,这里的第一个常量表达式就是一维数组的个数,第二个常量表达式代表着每一个一维数组中元素的个数。
(2)二维数组的初始化
①int a[3][4] ={{1,2,3,4},{5,6,7,8},{9,10,11,12}};//对每一个一维数组的每个元素赋初值
②int a[3][4] ={1,2,3,4,5,6,7,8,9,10,11,12};//按下标顺序给每一个元素赋初值(从a[0][0]到a[2][3]);
③int a[3][4] = {{2},{5},{1}};//对部分元素赋值,其他为0值(对a[0][0],a[1][0],a[2][0]赋值)
2.4二维数组的地址及数组名操作命令含义
(1)二维数组示意图
同样这里二维数组名a为指针常量,它代表首个一维数组的地址。
(2)对数组名的操作命令及解析
①&a:二维数组a的地址(对二维数组名取地址)
②*(&a):对二维数组a的地址取值等于首个一维数组a[0][ ]的地址
③*(a):首个一维数组的首元素的地址
④*(a + i):第i+1个一维数组的首元素的地址
⑤*(a+i)+j:第i+1个一维数组的第j+1个元素的地址
⑥*(*(a+i)+j):第i+1个一维数组的第j+1个元素的值
2.5数组名的总结
任何维度的数组名代表的含义是它代表着比它小一级别的首个元素的地址。例如:三维数组名代表首个二维数组的地址;四维数组名代表首个三维数组的地址。
三、静态数组与动态数组
静态数组是在定义是就已经在栈上分配了空间大小,在运行时这个大小不能改变,如:
int a[10];
动态数组的大小是在运行是给定,即,运行时在堆上分配一定的存储空间,同时运行时还可以改变其大小。
动态数组是相对于静态数组而言,从“动”字我们也可以看出它的灵活性,静态数组的长度是预先定义好的,在整个程序中,一旦给定大小后就无法改变。而动态数组则不然,它可以随程序需要而重新指定大小。动态数组的内存空间是从堆动态分配的。是通过执行代码而为其分配存储空间。当程序执行到我们编写的分配语句时,才为其分配。对于静态数组,其创建非常方便,使用完也无需释放,要引用也简单,但是创建后无法改变其大小是其致命弱点!对于动态数组,其创建麻烦,使用完必须由程序员自己释放,否则将会引起内存泄露。但其使用非常灵活,能根据程序需要动态分配大小。所以相对于静态数组的来说我们对于使用动态数组有很大的自由度。
在创建动态数组的过程中我们要遵循一个原则,那就是在创建的时候从外层往里层,逐层创建;而释放的时候从里层往外层,逐层释放,比如创建一维动态数组
————————————
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n1,i;
int *array;
printf("请输入所要创建的一维动态数组的长度:");
scanf("%d",&n1);
array=(int*)calloc(n1,sizeof(int));
for(i=0;i<n1;i++)
{
printf("%d\t",array[i]);
}
printf("\n");
for(i=0;i<n1;i++)
{
array[i]=i+1;
printf("%d\t",array[i]);
}
free(array);//释放第一维指针
return 0;
}
运行结果为
请输入所要创建的一维动态数组的长度:4
0 0 0 0
1 2 3 4 Press any key to continue
二位动态数组的话,则是先给一维数组分配空间(第一维),再给一维数组内部分配(第二维),释放则是从内向外,先给第二维指针释放,再第一维
四、数组的函数传参
1、数组传参
●传一维数组时,形参用同数据类型的指针。如:char str[100]传参时形参可写为char *str;
●传二维数组时,形参用同数据类型的一维数组指针。如:char str[2][100]传参时形参为char(*str)[100];
●传三维数组时,形参用同数据类型的二维数组指针。如:char str[2][3][100]传参时形参为char(*str)[3][100]
总结:对于数组的传参,其形参为对应的指针,一维数组为指针,二维数组为一维数组指针,三维数组为二维数组指针,以此类推。
2、指针数组传参
指针数组:数组里面的元素都是指针。
因为数组是用对应的指针作为形参,而指针又需要指针的指针作为形参,故传指针数组时用指针的指针作为形参。例如:char *src[100]的形参为char **src。
五、数组与指针的区别
1、从内存分配上看,数组是静态分配,指针是动态分配。
2、数组的元素过多时会出现数组越界;对于指针则容易产生内存泄漏。
3、数组的访问方式为直接访问,访问效率高;指针的访问方式为间接访问,访问效率低。
4、数组分配的空间是连续的,指针分配的空间可能不是连续的。