一、一维数组
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)
文章详细介绍了C语言中一维数组和二维数组的定义、初始化方法,以及它们与指针的关系。在函数参数中,数组通常以指针形式传递,允许在函数内部修改数组内容。二维数组按行优先存储,可以被视为数组的数组。此外,文章还讨论了动态数组的概念,强调了初始化时需注意的数组大小问题。
3506





