一、一维数组
1.1定义
一维数组的定义需要指定数组长度,方法有两种,一种是通过数组标号指定,另一种是数组标号留空,使用初始化值得个数指定长度。如下:
char a[5]; char a[] = {1,1,1,1,1};
1.2初始化
一维数组得初始化没什么好说得。需要知道的是,局部变量的值是随机值,对于局部数组变量来说,只要指定一个元素值进行初始化,那么其他未指定得元素值都会被初始化未0。
1.3 一维数组与指针
一维数组的数组名指向数组元素首地址,也是数组首元素的地址。即:char a[3];则a = &a[0]。
换句话说一个指向一维数组的指针p:char *p = a。就类似于char p[3],有p + i = a + i,p[i] = a[i] , *(p + i) = p[i] 。
注意点:
①是p++是可以的,= p + sizeof(数组元素类型),但a不可以进行++操作。
②指向数组的指针在移动的时候,是以数组元素类型为单位的,比如char型数组,指向它的指针每加1,就是走1byte,int型数组,指向它的指针每加1,指针地址就走4byte。容易犯错。
1.4 一维数组作为函数参数
(1)使用数组名做函数参数,那么也就类似是指针做参数,如果在函数中修改了数组的内容。在上层函数中实参数组的内容也就被修改了。
(2)函数的形式参数可以是数组名,也可以是指针: void test(char c[])或void test(char *p)
二、二维数组
2.1定义
二维数组的元素在内存中的存放是行优先,先顺序存放行的所有数据,再接着存放下一行的所有数据。
①不带初始化的定义:必须指定两个维度的长度。
②带初始化的定义:[]中必须指定列维度的长度,这样编译器能计算行数。
如下:
char a[3][2]; char a[][2] = {1,1,1,1,1};
2.2初始化
二维数组得初始化也没什么好说得。需要知道的是,局部变量的值是随机值,对于局部数组变量来说,只要指定一个元素值进行初始化,那么其他未指定得元素值都会被初始化未0。
2.3 二维数组与指针
(1)二维数组可以看作数组的数组,a为数组名,有三个元素分别是a[0],a[1],a[2],这三个元素有都是一维数组的数组名(或者地址)。因此二维数组的数组a也可以看作是指针数组。写出如下形式
char *p[3] = {a[0],a[1],a[2]};
(2)a指向数组名a指向数组元素首地址,也是数组首行地址,也就是首行首列元素地址。即:
a = a[0] = &a[0][0]
(3)二维数组行地址:a+i 或者a[i]就是第i行首地址。二维数组列元素地址a[i]+j表示第i行第j列元素地址。
a[i] <==> a +i <==> *(a + i),都表示的第i行的地址。
(4)指向元素的指针和指向一维数组的指针
char *p = a[0];//表示p指向首行地址,p+1表示a[0][1]地址 char (*p)[2] = a;//p是指向一个有2个元素的一维数组的指针,这里就表示p指向二维数组a的第0行。自然p+1或p[1]表示第1行地址。
2.4 二维数组作为函数参数
有以下几种方式:
(1)形参以二维数组的形式
形参中至少必须要指定第二维的大小:因为有第二维长度就可以计算第一维长度了。另外编译器不会检查形参的第一维长度,所以形参第一维长度无所谓。
函数形参:void func(char array[][2]) 传递实参:func(a) 在函数func中对二维数组的使用:可直接使用array[i][j]
(2)形参使用指向一维数组的指针,实参采用二维数组名
函数形参:void func(char (*array)[2]) 传递实参:func(a) 在函数func中对二维数组的使用:可直接使用array[i][j]
(3)形参采用指向指针的指针,实参采用指针数组
函数形参:void func(char **array) 传递实参:实参不能直接用二维数组名这些,需要转换以下: char *p[3] = {a[0],a[1],a[2]}; func(p,3,5); 在函数func中对二维数组的使用:可直接使用array[i][j]
2.5 例题
/*题目:对数组元素为0的元素,则将其所在行和列所有元素都设置为0,clear_array的空间复杂度要小于O(m*n) *思路就是:遍历每个元素,记录为0时候的坐标,遍历完以后把所有i代表的行清0,j代表的列清0 *涉及知识点:多维数组的使用:作为函数参数的用法 */ #include <stdio.h> typedef char elemType; elemType a[3][5] ={ 0,2,1,3,4, 2,6,0,1,5, 1,1,1,0,9 }; void clear_array(elemType **array, int x, int y); int main(void) { /* 对多维数组求行、列的方式 */ int row,column; row = sizeof(a)/sizeof(a[0]) ; printf("row = %d\n",row); column = sizeof(a[0])/sizeof(elemType); printf("column = %d\n",column); elemType *p[3] = {a[0],a[1],a[2]}; clear_array(p,row,column); #if 1 //打印查看结果 int i,j; for(i=0; i < row; i++) { for(j=0; j < column; j++) { printf("%d,",a[i][j]); } printf("\n"); } #endif return 0; } void clear_array(elemType **array, int x, int y) { int i,j; elemType column[y]; memset(column,0,y*sizeof(elemType)); for(i=0; i < x; i++) { for(j=0; j < y; j++) { if(array[i][j] == 0) { column[j] = 1;//记录下为0的列号 memset(&array[i][0],0,y*sizeof(elemType));//该行清0 break;//某行有0,那么就不用再检查该行剩下的数据了 } } } //现在来处理列 for(j=0; j < y; j++) { if(column[j] != 0) { for(i=0; i < x; i++) { array[i][j] = 0; } } } }
三、动态数组的定义和初始化
动态数组,指的是数组的大小,依赖于程序运行过程中的结果变量的值。
如:
动态数组定义: scanf("%d",&array_len); char b[array_len];
定义是可以的,但初始化不能在定义的时候给其赋值,因为此时arrray_len还未知,编译器编译的时候不知道要给该数组b分配多少内存空间。
错误的初始化方式: scanf("%d",&array_len); char b[array_len] = {0};
两种正确的初始化方式:
方式1:使用for循环进行初始化清0
scanf("%d",&array_len); char b[array_len]; for(j=0; j < array_len; j++) { b[j]=0; }
方式2:使用memset进行初始化清0
scanf("%d",&array_len); char b[array_len]; memset(b,0,array_len); 注意:这种方式需要注意,memset函数参数3表示byte数,所以这里需要根据数组数据类型,乘上相应的数据size。如:数组是int型,那么这里要memset的参数3,要修改为array_len * sizeof(int)