一、二维数组的基本用法
数组的特性:长度固定 、 同类型、 有编号(先行后列)
逻辑造型:表格矩阵状
1.二维数组声明生成: 类型 数组名[行数][列数]
int a;
int arr1[10];
int ge[3][4];
二维数组称为一维数组的一维数组
2.数组元素(成员)的使用:数组名[先行][后列]
ge[0][0] = 1; ge[0][3] = 2;
ge[2][0] = 3; ge[2][3] = 4;
注意事项:不要下标越界使用。
3.循环遍历 每个成员
int hs = sizeof(ge) / sizeof(ge[0]);
int ks = sizeof(ge[0]) / sizeof(ge[0][0]);
for (int i = 0; i < hs; i++)
{
for (int j = 0; j < ks; j++)
{
printf("%d ", ge[i][j]);
}
printf("\n");
}
这里已经定义了二维数组ge,如果单独使用那么他的内存空间就是整个二维数组,如果是以ge[]的形式代表的就是数组中一行的空间,要是ge[][]就是精确到数组中某一个成员的空间。可以利用这个来求二维数组中有几行几列。
二、二维数组初始化
二维数组 在 声明的同时 直接初始化赋值
1.完全初始化:形式1:一维摸样 形式2:{}行方式
int arr1[2][3] = { 1,2,3,4,5,6 };
int arr2[2][3] = { {1,2,3},{4,5,6} };
2.不完全初始化、其它成员默认 0
int arr3[2][3] = { 1,2,3 };
int arr4[2][3] = { {1,2},{4} };
3.初始化成员个数 列数不能省略,根据列数自动决定行数。
int a1[][3] = { 1,3,4,6,7,8,98,9,2 };//只能输入列 不能输入行
int a2[][5] = { {1},{2,3},{8,9,10} };
切记,只能输入列,不能输入行。
通过调试器查看存储内容
三、二维数组与指针
1.用int指针遍历数组元素,证明二维数组在内存中是连续的
int arr[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int* p = &arr[0][0];
for (int i = 0; i < 3 * 4; i++)
{
printf("%d ", *p++);
}
2.数组名的用法
A:找到 某行的首地址
printf("\n%d %d %d\n", arr+0, arr + 1, arr + 2);
二维数组名代表第0行地址,数组名+1代表行移动;一维数组名+1是代表列移动。
B:得到 某行的存储空间
//printf("\n%d %d %d\n", *(arr + 0), *(arr + 1), *(arr + 2));//只打印了空间的地址
printf("\n%d %d %d\n", sizeof(*(arr + 0)), sizeof(*(arr + 1)), sizeof(*(arr + 2)));
printf("\n%d %d %d\n", sizeof(arr[0]), sizeof(arr[1]), sizeof(arr[2]));
因为二维数组用arr[]表示的是行,所以他只会得到某行的空间,并不会将每一行的数据都进行打印。
C:找到某行内--某列的地址
printf("\n%d %d %d\n", *(arr + 1) + 0, *(arr + 1) + 1, *(arr + 1) + 2);//在行空间的基础上移动是列的地址,就可以找到列的地址
printf("\n%d %d %d\n", arr[1] + 0, arr[1] + 1, arr[1] + 2);
在行空间的基础上移动是列的地址,就可以找到列的地址
D:得到某行 某列的存储空间
printf("\n%d %d %d\n", *(*(arr + 1) + 0), *(*(arr + 1) + 1), *(*(arr + 1) + 2));
printf("\n%d %d %d\n", *(arr[1] + 0), *(arr[1] + 1), *(arr[1] + 2));
printf("\n%d %d %d\n", arr[1][0], arr[1][1], arr[1][2]);
通过ABCD也可以看出,这其实就是二维数组的推导过程
E:跨度整个二维数组
printf("%d %d\n", &arr, &arr + 1);
&arr代表整个二维数组的首地址,所以+1后找到的是数组后面的地址
3.利用指向一维数组的指针 遍历每一行的首地址
4.利用指向一维数组的指针 遍历每一行 每一个元素成员
(这里的3和4一起说)
int(*ph)[4] = arr;
for (int h = 0; h < 3; h++)
{
//printf("%d \n", ph++);
/*4 . 利用指向一维数组的指针 遍历每一行 每一个元素成员*/
printf("%d %d %d %d\n", **ph, (*ph)[1], (*ph)[2], *(*ph + 3));//不要认为这里的ph是二级指针
ph++;
}
这里的一维数组指针指向的是二维数组每一行的首地址,再通过*操作就可以确定每一行的空间,就可以再次利用[]运算找到每一行中成员的空间了。
5.利用指向二维数组的指针 遍历每一行 每一个元素成员
int(*pm)[3][4] = &arr;
for (int h = 0; h < 3; h++)
{
for (int k = 0; k < 4; k++)
{
printf("%d %d %d\n", arr[h][k],(*pm)[h][k],*(*((*pm)+h)+k));
}
}
这里*pm指向的就是整个二维数组,所以需要先进性行查找在进行列查找就可以得到目标成员数据。故需要进行两次[]运算。
四、多维数组原理
1.三维数组的声明
int arr[3][4][5] = {1,2,3,4,5,6,7,8,9};
三维数组的初始化原理与一维二维相同,就不再赘述了,利用三维数组名+下标的遍历方法也相似,就是利用一个三层嵌套循环即可。
2.三维数组的遍历:用int型变量的指针(列指针)
int* pl = &arr[0][0][0];
3.三维数组的遍历:用int型指向一维数组的指针(行指针)
int(*ph)[5] = &arr[0][0];
4.三维数组的遍历:用int型指向二维数组的指针(平面指针)
int(*pm)[4][5] = &arr[0];
5.三维数组的遍历:用int型指向三维数组的指针(立体指针)
int(*pt)[3][4][5] = &arr;
从这几种遍历方法定义指针时可以看出一些规律,如果是普通类型的指针那么它所指向的就是三维数组中某一成员的地址;如果是一维数组指针,那么他指向的就是三维数组中某一行的地址;如果是二维数组指针,那么它所指向的就是三维数组中某一平面的地址;如果时三维数组指针,那么它指向的就是三维数组本身的地址。