二维数组的创建和初始化
通过上一章节,我讲解了一维数组的的创建与初始化,这节我们继续来学习二维数组的变化。
目录
2.1 二维数组的创建
# include<stdio.h>
int main() {
//数组创建
int arr[3][4];
char arr[3][5];
double arr[2][4];
二维数组可以看成是一个坐标系,由横纵两点明确着数组元素的位置。
2.2 二维数组的初始化
//数组初始化
int arr[3][4] = {1,2,3,4};
int arr[3][4] = {{1,2},{4,5}};
int arr[][4] = {{2,3},{4,5}};//二维数组如果有初始化,行可以省略,列不能省略
在二维数组的初始化中,第一个arr是由三行四列组成的数组,共有12个元素构成。但赋值元素却只有四个,系统会根据数组列数去给元素排序,那么1,2,3,4会先排列到第一行,之后的元素便都赋值为0,放到第二三行中放满即可。你可以理解为逢四进一(每一行只要有四个元素,下一个元素便自动放到下一行开头位置)。
所以是1 2 3 4
0 0 0 0
0 0 0 0
在第二个arr中,初始化列表中,用花括号划分了区域 ,{1,2},{4,5}这是表明虽然每一行要放四个元素,但1245的排列顺序是
1 2 0 0
4 5 0 0
0 0 0 0
花括号的排列优先级是高于二维数组行列[ ]操作符的
第三个arr省略了行下标操作符的值,结果为
2 3 0 0
4 5 0 0
行下标的省略并不影响二维数组的排列,系统会以最少的行数去分配数组空间,但列下标的省略是不允许的, C语言中明确规定了二维数组只有列[ ] 下标操作符不可以省略 !
2.3 二维数组的使用
二维数组的赋值,遍历也是遵循下标从0开始的原则。
int arr2[3][4] = { 0 };
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 4; j++)
{
arr2[i][j] = i * 4 + j;
}
}
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 4; j++)
{
printf("%d ", arr2[i][j]);
}
printf("\n");
}
2.4 二维数组在内存中的存储
#include <stdio.h>
int main()
{
int arr[3][4];
int i = 0;
for(i=0; i<3; i++)
{
int j = 0;
for(j=0; j<4; j++)
{
printf("&arr[%d][%d] = %p\n", i, j,&arr[i][j]);
}
}
return 0;
}
由图可知,二维数组在内存中的存储仍是连续性的。
其实二维数组也好比是一维数组,一维数组是元素的数组,而二维数组转换为一维数组时,是一维数组的数组。
那么接下来便引出一个问题:二维数组名的表示含义。
通过上节课的讲解,一维数组名一般表示首元素a[0]的地址
但是有2个例外:
1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址 。
那么二维数组中 arr还是表示首元素a[0][0]的地址吗?
答案肯定是:错误的。刚才讲到二维数组若是转化成一维数组,它是由一维数组组成的数组,它的首元素地址其实是第一行所有元素的地址。
int a3[3][4] = { 0 };
printf("%p\n", a3);
printf("%p\n", a3+1);
printf("%p\n", &a3);
printf("%p\n", &a3+1);
从上图就可以说明:一行的字节大小为16字节(4*4),数组名+1则会跳过一整行的字节数,所以二维数组arr代表的是首行地址。
而&arr代表整个数组地址时,+1会跳过48字节(12*4)一整个数组地址。
以上就是对二维数组的讲解了。