【C语言】深入理解数组(一维数组、二维数组的表示及数组与指针的关系)
一、一维数组的定义与初始化1.一维数组的定义一维数组也称向量,它用以组织具有一维顺序关系的一组同类型的数据。一维数组的定义方式:数据类型 数组名[常量表达式]类型说明符表示数组中所有元素的类型;常量表达式指数组的长度(即数组中存放元素的个数)例如:int array[5];上述代码 int 表示数组元素的类型,array 是数组的名称,5是指数组的长度。数组占据的内存空间是连续的,所以很容易计算出
一、一维数组的定义与初始化
1.一维数组的定义
一维数组也称向量,它用以组织具有一维顺序关系的一组同类型的数据。
一维数组的定义方式:
数据类型 数组名[常量表达式]
类型说明符表示数组中所有元素的类型;常量表达式指数组的长度(即数组中存放元素的个数)
例如:int array[5];
上述代码 int 表示数组元素的类型,array 是数组的名称,5是指数组的长度。
数组占据的内存空间是连续的,所以很容易计算出数组占据的内存大小( 数组长度*sizeof(数据类型))和每个元素所对应的内存首地址。
上述数组array占据的内存大小为:5*sizeof(int)=20字节
完成数组的定义后,编译器根据数组定义语句中提供的数据类型和数组长度给数组变量分配适当的内存空间。如果想要使用数组操作数据,还需要对数组进行初始化。
2.一维数组的初始化
三种常见的数组初始化元素的方式:
(1)直接对数组中所有元素赋初始值。
int a[4]={1,2,3,4};
表示定义了一个长度为4的整型数组a,a数组中的元素依次是1,2,3,4.
(2)只对数组一部分元素进行赋值
int b[5]={1,2,3};
表示定义了一个长度为5的整型数组b,数组的前三个元素依次为1,2,3,其他的元素的值会被默认设置为0.
(3)对数组全部元素赋值,但不指定长度
int c[]={1,2,3,4};
系统会根据赋值号右边的初始值列表中给出的初值个数自动设置数组的长度。
【注意】
- 数组下标是用方括号括起来的,而不是圆括号
- 数据类型可以是基本类型,也可以是指针、结构体等
- 数组名的命名规则和变量名的命名规则相同
二、一维数组的引用
当需要访问数组中的元素时,需要通过数组名和下标来引用数组元素,一维数组的元素引用方式如下:
数组名[下标]
下标是指元素在数组中的位置,元素的下标从0开始,也就是一个长度为6的数组,下标为0~5;
访问数组元素时,下标不能超出这个范围(0~(数组长度-1)),否则程序会报错。
三、 数组的非法操作
(1)用一个已初始化的数组为另一个数组赋值
int x[3]={1,2,3};
int y[3];
y=x;//错误操作
(2)对数组进行整体输入输出
printf()和scanf()仅仅支持字符数组整体的输入和输出,不支持其他类型的数组整体输入输出。对于不能整体输入输出的数组,必须以元素为单位进行操作。
int a[3]={1,2,3};
printf("%d",a);//错误操作
printf("%d %d %d",a[0],a[1],a[2]);//正确操作
(3)数组与数组之间不能进行比较
int a[3]={1,2,3};
int b[3]={4,5,6};
if(a>b)...//错误操作
(4)数组与数组之间不能进行运算
int a[3]={1,2,3};
int b[3]={4,5,6};
a+=b;//错误操作
四、二维数组的定义和初始化
1.二维数组的定义
二维数组的定义方式如下:
类型说明符 数组名[常量表达式1] [常量表达式2]
常量表达式1称为“行下标”,常量表达式2称为“列下标”
int a[3][4];
表示定义一个3行4列的二维整型数组a.
二维数组a的元素分布情况:
多维数组的元素存储顺序按照右边的下标率先变化的原则,称为行主序。
2.二维数组的初始化
三种常见的二维数组初始化方式:
(1)按行给二维数组赋初值
int a[2][3]={{1,2,3},{4,5,6}};
(2)将所有的数组元素按行顺序写在一个大括号内
int a[2][3]={1,2,3,4,5,6};
(3)对部分数组元素进行赋值
int a[3][3]={{1},{2,3},{4,5,6}};
对于没有赋初始值的元素,系统自动赋值为0.
【注意】 二维数组的行下标可以省略,但列下标不能省略
int a[2][3]={1,2,3,4,5,6};
可以写成int a[][3]={1,2,3,4,5,6};
系统会根据固定的列数,将后面的数值进行划分,自动将行数定位2.
五、二维数组的引用
二维数组的引用方式同一维数组是一样的,通过数组名和下标进行数组元素的引用
数组名 [行下标][列下标];
访问时也不能超过数组的范围。
int a[3][4];
a[3][4]=3;//错误操作,行下标范围0~2,列下标范围0~3
六、数组的深入探讨
(1)一维数组的数组名
C语言中,在几乎所有使用数组名的表达式中,数组名的值是一个指针常量,也就是数组第一个元素的地址。
它的类型取决于数组元素的类型:如果数据元素类型是int,那么数组名的类型就是“指向int的常量指针”,其他类型同理。
只有当数组名在表达式中使用时,编译器才会为它产生一个指针常量(注意这个值是一个指针常量,而不是指针变量)。
两种场合数组名不用指针常量来表示:
①当数组名作为sizeof()的操作符
sizeof返回整个数组的长度,而不是指向数组的指针的长度。
②数组名作为单目操作符&的操作数
对数组名取址产生的是一个指向数组的指针,而不是一个指向某个指针常量的指针。
(2)一维数组的下标引用
表达式*(b+3)含义:b是一个指向整型的指针,加法运算结果仍是一个指向整型的指针,该指针指向的是数组第一个元素后3个整型长度的位置,然后,间接访问这个位置(取这个位置的值)。
这与下标引用b[3]的过程完全一样。所以除了优先级外,下标引用和间接访问完全相同。
即:array[下标]和*(array+(下标))等同
在使用下标引用的地方可以使用对等的指针表达式来代替。
案例分析:
int array[10];
int *ap=array+2
用array的对等表达式表示ap的表达式
ap: array+2或 &(array[2])
*ap: array[2]或 *(array+2)
ap[0]:array[2](这是一个正确的表达,因为C语言的下标引用和间接访问是一样的,所以ap[0]和*(ap+0)是对等的,所以结果和上一个表达式一致。)
ap+6: array[8]或 &(array[8])
*ap+6: array[2]+6(因为间接访问符*优先级要高于运算符+)
*(ap+6):array[8]
ap[-1]: array[1](还是这个道理:下标引用就是间接访问:*(ap+(-1))
(3)二维数组的数组名
int matrix[3][5];
matrix 类型是一个指向一个包含5个整型元素的数组的指针。
它的值是:它指向包含5个整型元素的第一个子数组。
(4)二维数组的下标引用
matrix[1][2]访问的元素如下:
表达式:matrix+1(1是根据包含5个元素的数组的调整,所以它指向matrix的下一行)
表达式:*(matrix+1)
实际上标识了一个包含5个整型元素的子数组。数组名的值是一个常量指针,指向数组的第一个元素。
表达式:*(matrix+1)+3
前一个表达式是一个指向整型值的指针,所以5是根据整型的长度进行调整,结果还是一个指针,指向刚才位置的后面的第3个位置。
表达式:*(*(matrix+1)+3)
该表达式就是间接访问那个位置的值。
根据间接访问可以用下标表示*(matrix+1)等同于matrix[1], *(matrix[1]+3)继续替换则变成了matrix[1][3]。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)