网站首页 > 精选教程 正文
引言
数组作为我们日常编写代码时最用常见的数据类型之一, 其最大的特点就是将统一的数据类型的变量在内存中连续分布,方便我们对其读写访问。之前我们从各个方面分析过一维数组,如内存分布,数组符号含义,数组下标和指针访问等等。二维数组与一维数组本质上都是数组,区别在于二维数组多了一个维度, 所谓的维度可以通俗的理解成:如果一个班级有50个的学生,表示为int students[50], 且该年段有6个这样的班级, 就可以表示为int class[6][50]; 好了,接下来我们就通过几个方面来分析下二维数组以及与指针结合应用。
二维数组和多维数组的应用场景
从内存分布图看,一维数组和二维数组没有本质差别, 都是在内存中连续分布,如一维数组中的a[9]就等于二维数组中的a[1][4],两者代表的内存地址是一致的。
既然二维数组都可以用一维数组来表示,那二维数组存在的意义和价值呢?其实二维数组和一维数组在内存使用效率、访问效率上是完全一样的。只是在某种情况下用二维数组而不用一维数组,原因在于二维数组好理解、代码好写、利于组织。比如用一维数组用来表示直线;二维数组用来描述平面(x,y),如屏幕坐标; 用三维数组表示立体空间(x, y, z),如四轴飞行器计算角度,姿态就用到三维数组。
二维数组的访问方式
随便回顾下一维数组的访问两种方式, 以int a[10]为例,
int a[10];
int *p = a;
a[0] 就等同于 *(p+0),
a[9] 就等同于 *(p+9)
一般规律:a[i] = *(p + i)
因此我们可以用a[4]或*(p+4)来访问数组a的第5个元素(从元素0开始)。
二维数组同样可以使用下标方式和指针方式访问其元素,以int a[2][5]为例:
int a[2][5];
int (*p)[5] = &a[0]; //定义一个指针p,指向类型为[5]数组
a[0][3] 就等同于 *(*(p+0) + 3)
a[1][4] 就等同于 *(*(p+1) + 4)
一般规律: a[i][j] = *(*(p+i) + j)
具体代码:
#include <stdio.h>
int main(void)
{
int a[2][5] = {{1,2,3,4,5},{6,7,8,9,10}};
int (*p)[5] = a; //定义一个数组指针p,并将二维数组的第一维数组首元素首地址赋值
//这里需要注意的是 a(等同于&a[0]) 和 &a的区别
printf("a[1][3] = %d. *(*(p+1)+3) = %d.\n", a[1][3], *(*(p+1)+3));
return 0;
}
运行结果:
这里需要大家能够理解: int (*p)[5] 与 a(或&a[0])的类型是匹配的!!!这是理解二维数组用指针访问的基础,也是二维数组的本质,其实下标式访问只是编译器提供的语法糖,方便初学者使用,但是使用指针式才是真正理解二维数组的关键和判断标准!
二维数组中符号理解
进一步理解二维数组中涉及的一些符号:
#include <stdio.h>
int main(void)
{
int a[2][5] = {{1,2,3,4,5},{6,7,8,9,10}};
int *p1 = a[0];
int *p2 = &a[0][0];
printf("p1 = %p, *p2 = %p.\n", p1, p2 );
return 0;
}
编译,无错误无警告,且运行结果:
这里我们将p1, p2拎出来说明下为什么分别与a[0], &a[0][0]类型是一致的:
a[0]表示二维数组的第一维的第一个元素,相当于是第二维的整体数组的数组名。数组名又表示数组首元素首地址,因此a[0]等同于&a[0][0](是指向int 类型的指针),因此与p1, p2(指向int类型的指针)类型是完全一致的。
那么通过p1和p2来访问下二维数组:
编译无错误无警告,且运行结果:
通过指针访问二维数组的第2个整体数组:
int *p3 = a[1];
int *p4 = &a[1][0];
printf("a[1][4] = %d.\n", *(p3+4));
printf("a[1][4] = %d.\n", *(p4+4));
编译无错误无警告,且运行结果:
总结
今天讲的可能有点绕, 需要大家结合二维数组在内存分布来理解一些符号,如a, a[0], &a等,并理解与指针的赋值,通过指针方式来访问和读写二维数组中的各个元素,尤其是理解: *(*(p+i) + j)来访问a[i][j]元素。记住下标式来访问二维数组只是编译器提供的语法糖,指针才是深入学习C语言的关键!
猜你喜欢
- 2024-11-16 面向JVM编译-类实例、数组的创建和使用
- 2024-11-16 来,一起聊聊Excel中的数组(excel数组公式有哪些)
- 2024-11-16 数组的维数及数组公式的讲解(数组维的大小)
- 2024-11-16 C语言中数组的类型和使用(c语言中数组的概念及作用)
- 2024-11-16 C# - 多维与交错数组 036(交错数组和多维数组有何区别?)
- 2024-11-16 Numpy第6练:如何操控数组的维度与形状?干货满满!
- 2024-11-16 NumPy之:多维数组中的线性代数(numpy 多维数组)
- 2024-11-16 S7-1200 数组数据类型(ARRAY)(s71200plc数据类型)
- 2024-11-16 JAVA中如何调用matlab并返回运算结果?
- 2024-11-16 Java基础03(java基础案例教程第二版)
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)