一 : 二维数组
1: 二维数组的内存映像
(1)一维数组在内存中是多个连续分布的多个内存单元组成的,而二维数组在内存中也是多个连续分布内存单元组成的
int a[10]; //一维数组
int a[2][5]; //二维数组
(2)从内存角度上看,一维数组跟二维数组没有本质差别
//都有十个int类型的元素,在内存中是连续分布的多个内存单元
int a[10] = {1,2,3,4,5,6,7,8,9,10}; //一维数组
int a[2][5] = {{1,2,3,4,5},{6,7,8,9,10}}; //二维数组
(3)二维数组int a[2][5];和一维数组intb[10]没有本质差别,可以将其对应关系给写下来
a[0][0] a[0][1] a[0][4] a[1][0] a[1][1] a[1][4]
b[0] b[1] b[4] b[5] b[6] b[9]
(4)既然二维数组都可以用一维数组来表示,那二维数组存在的价值和意义在哪里?二维数组和一维数组在内存使用效率和访问效率是一样的(或者说差异是忽略不计的),在某种情况下用二维数组而不用一维数组原因在于二维数组好理解、代码好写、易于组织
//譬如说管理从1到10的十个数,要将小于等于5和大于5小于10的数区分开
#include <stdio.h>
int main(void)
{
int b[10] = {1,2,3,4,5,6,7,8,9,10}; //一维数组存放十个数
int a[2][5] = {{1,2,3,4,5},{6,7,8,9,10}}; //二维数组存放十个数
//从视觉角度来看一维数组b存放了十个数,但是没有区分开
//二维数组a在第一维中存放了两个元素,第一个元素是一个数组,数组里面存放的是小于等于5的数。
//第二个元素也是一个数组里面存放的是大于5小于10的数
return 0;
}
(5)总结:我们使用二维数组(C语言提供二维数组),并不是必须,而是为了简化编程的一种方式,一维数组的出现也不是必然的,也是为了简化编程
2 :二维数组哪个是第一维哪个是第二维?
(1)二维数组int a[3][4] 中,3是第一维,4是第二维。
(2)结合内存映像来理解二维数组的第一维和第二维的意义。首先第一维是最外面的一层数组,所以inta[3][4]这个数组里面有三个元素,其中每个元素中又是一个含有4个元素的数组(这个数组就是第二维)
(3)总结:二维数组第一维是最外部的那一层,第一维本身是一个数组,这个数组中存储的元素是个一维数组;二维数组的第二维是里面的那一层,第二维本身是一个一维数组,数组中存储的元素是普通元素,第二维这个一维数组本身作为元素存储在第一维的二维数组中
3 :二维数组的下标访问和指针访问
(1)一维数组的两种访问方式。以int b[10]为例,int *p = b;
b[0] 等同于 *(p+0) b[9] 等同于 *(p+9) b[i] 等同于 *(p+i)
(2)二维数组的两种访问方式。以int a[2] [5] 为例,(合适的类型) p = a;
a[0][[0] 等同于 *(*(p+0)+0) a[i][j] 等同于*(*(p+i)+j)
4 :二维数组的应用和更多维数组
(1)最简单的情况,有10个学生成绩要统计;如果这10个学生没有差别的一组,就用b[10];如果这10个学生天然就分为两组,每组5个,就适合用 int[2][5]来管理
(2)最常用的情况:一维数组用来表示直线,二维数组用来描述平面。数学上,用平面直角坐标系来比拟二维数组就很好理解了。
(3)三维数组和三维坐标系来比拟理解。三维数组其实就是立体空间
(4)四维数组也是可以存在的,但是数学上有意义,现在空间中没有对应(因为人类生存的宇宙是三维的)
总结:一般常用最多就到二维数组,三维数组除了做一些特殊与数学运算有关的之外基本用不到。(四轴飞行器中运算飞行器的角度、姿态时就要用到三维数组)
二 : 二维数组的运算和指针
1 :指针指向二维数组的数组名字
(1)二维数组的数组名表示二维数组第一维数组中首元素(也就是的第二维的数组)的首地址
(2)二维数组的数组名a等同于&a[0],这和一维数组的符号含义是相符的
(3)用数组指针来指向二维数组的数组名类型是相匹配的
#include <stdio.h>
int main(void)
{
int a[2][5] = {{1,2,3,4,5},{6,7,8,9,10}};
//int *p = a; //定义一个一重指针指向二维数组a,编译器提示错误类型不匹配
//int **p1 = a; //定义一个二重指针指向二维数组a,编译器提示错误类型不匹配
int (*p)[5]; //定义一个数组指针,指针指向一个数组,数组里面有五个int类型的元素
p = a; //a是二维数组的数组名,作右值时表示二维数组第一维的首元素首地址
//等同于&a[0]
return 0;
}
2 : 指针指向二维数组的第一维
(1)用int *p来指向二维数组的第一维a[i]
//指针指向二维数组的第一维
#include <stdio.h>
int main(void)
{
//int *p2 = &a[0]; //不可以
int *p2 = a[0]; //a[0]表示二维数组中的第一维的第一个元素,相当于是二
//维整体的数组
//的数组名。数组名又表示数组的首元素首地址,因此a[0]
//就等同&a[0[0]
int *p3 = &a[0][0]; //无警告无错误
printf("a[0][1] = %d\n",*(p2+1));
//如果要访问a[1][1]的话
int *p4 = a[1]; //a[1]表示二维数组中的第一维的第二个元素
return 0;
}
3 : 指针指向二维数组的第二维
(1)二维数组的第二维其实已经是普通变量了(a[1][1]其实就是int类型的7),已经不能用指针和它相互赋值了
(2)除非int *p = &a[i][j]; ,类似指针指向二维数组的第一维
总结 :二维数组与指针的纠葛关键两点
1:数组中各个符号的含义
2:数组的指针式访问,尤其是二维数组的指针式访问