二维数组(解引用、指针数组、数组的指针)——C语言
二维数组
在说二维数组前先来说下一维数组中的指针数组和和数组的指针
一、一维数组中指针数组和数组指针的区别
指针数组:
int *p[];
[]的优先级比*高,首先它是一个数组,它的大小是5,它里面存放的数据类型是int *,也就是整型指针。 所以它叫指针数组,讲到底这个p是一个数组,数组内的元素是5个指针,而数组内的每一个指针指向一个int型的变量
数组的指针:
int (*p)[];
首先p是一个指针,指向大小为5的数组,因此这叫数组的指针,定义了一个指向5个元素的一维数组的指针。(括号优先)
二、两者在赋值时的区别
指针数组的赋值
#include <stdio.h> main()
{
int *p[];
int a = ; p[] = &a;
printf("%d", *p[]);
}
数组的指针的赋值
main()
{
int (*p)[];
int a[] = {, , , , }; p = &a;
printf("%d", *p[]);
}
三、关于数组的地址(这里只讨论一维\二维数组)
一维数组
int a[];
a表示的是数组的首地址,a等价于&a[0]
二维数组
int a[][] = {, , , };
a表示的整个数组的首地址,a[0]表示的是第一行的首地址,这两者者在数值上是一样的,但含义不同(或者说类型不同),数组名a是对于整个数组,a[0]是对于第一行
对二者(a、a[0])的地址是否相同进行验证
#include <stdio.h> int main()
{
int a[][] = {, , , }; printf("%p\n%p\n", a, a[]); return ;
}
运行结果

在用数组的地址进行赋值的时候,虽然三者值相同,但是三者不可随意混用(以int a[2][2]为例)
a--------是int (*)[2]型
a[0]-----是int *型
对于a[0]和&a[0][0],两个类型都是int *型的,所以下述两种赋值方法等价
第一种:
int a[][] = {, , , };
int *p;
p = a[];
第二种:
int a[][] = {, , , };
int *p;
p = &a[][];
对于int a[2][2]来说,如果将a[0]改为&a[0],那么&a[0]和a的类型相同,都为int (*)[2]类型,下面以int a[5][5]为例,列出了二维数组的元素在不同方式表达下的不同类型

也可以用一维指针数组来保存二维数组中某个元素的地址
int a[][] = {, , , };
int *p[];
p[] = &a[][];
printf("%d", *p[]);
四、二维数组的解引用
以二维数组a[2][3]={1, 2, 3, 4 ,5, 6};为例(第一维是行,第二维是列)
第一种:*(*a+1)--------等价于a[0][1],因为*的优先级比+高,所以先解引用,进入第二维在第二维里面地址+1,再次解引用得到元素值
第二种:*(*(a+1))------等价于a[1][0],比上面第一种多加了一个括号,括号优先级最高,先+1移动地址(注意是在第一维里面移动),然后解引用进入第二维,再解引用得到元素的值
第三种:*(&a[0][0]+1)--等价于a[0][1],这里使用了&取地址符,将原本表示第一个元素的a[0][0]返回到第二个维度,然后第二维地址+1,再解引用得到元素的值
为方便读者理解下面上图


补充:
请读者先看下面的代码
#include <stdio.h> main()
{
int a[][] = {, , , , , }; printf("%d***%d", *(a[]+), (*a+)[]);
}
*(a[1]+1)--------表示的是a[1][1]的值
(*a+1)[1]--------表示的是a[0][2]的值
为了方便描述先退回一维数组,以int a[5]来说,a表示的数组a的首地址,a[2]表示在a的基础上移动2个地址(注意a的类型是int *型的),再解引用得到元素的值,意思是a[2]
实际上包含了两步,第一步地址移动,第二步解引用得到元素的值(注意第二步,有点隐式转换的意思,经常被人忽略)
现在来解释上面的二维数组就容易多了
先来看第一个*(a[1]+1),a[1]代表第二行的首地址,注意这里的维度已经是第二维度了,然后括号优先第二维地址+1,最后解引用得到元素的值
来看第二个(*a+1)[1],这里提一句,因为[]的优先级是比*高的所以这里的括号不能去掉,第一步先解引用进入第二维度(*优先级高于+),然后第二维地址+1,然后再在当前基础上再移动一次地址,最后解引用
得到元素的值,这里可能有点绕,换个说法就是[1]是在当前维度进行移动,然后解引用(“当前维度”有点不太严谨,为了方便理解先将就这么用了)
拿a[2][1]来说,一共有四步,其中包含了两次地址移动,两次解引用,执行顺序是:地址移动->解引用->地址移动->解引用(这里提一句,[]的结合性是左结合的,所以在移动的时候先移动行(第一维)再移动列(第二维),小声BB)
详细步骤:第一步:在当前维度地址+2,因为a的维度是第一维,所以是第一维地址+2,即行+2
第二步:解引用进入第二维度
第三步:在当前维度地址+1,因为这时已经进入第二维,所以第二维地址+1,即列+1
第四步:解引用得到元素的值
二维数组(解引用、指针数组、数组的指针)——C语言的更多相关文章
- Gym 102028J 扫描线/二维差分 + 解方程
题意:有一个二维平面,以及n个操作,每个操作会选择一个矩形,使得这个二维平面的一部分被覆盖.现在你可以取消其中的2个操作,问最少有多少块地方会被覆盖? 思路:官方题解简洁明了,就不细说了:https: ...
- [luogu4479][BJWC2018]第k大斜率【二维偏序+二分+离散化+树状数组】
传送门 https://www.luogu.org/problemnew/show/P4479 题目描述 在平面直角坐标系上,有 n 个不同的点.任意两个不同的点确定了一条直线.请求出所有斜率存在的直 ...
- 【二维偏序】【树状数组】【权值分块】【分块】poj2352 Stars
经典问题:二维偏序.给定平面中的n个点,求每个点左下方的点的个数. 因为 所有点已经以y为第一关键字,x为第二关键字排好序,所以我们按读入顺序处理,仅仅需要计算x坐标小于<=某个点的点有多少个就 ...
- 摩托罗拉SE4500 德州仪器TI Omap37xx/AM3715/DM3730/AM3530 wince6.0/Windows Mobile 6.5平台 二维软解调试记录及相关解释
现在安卓大行其道,不是高通,就是MTK,甚至于很多人不知道还有德州仪器这个平台了,关于如何在德州仪器Omap37xx平台上调试SE4500,网络上除了针对SE4500的几个pdf文档介绍之外,没有任何 ...
- java基础5 (一维)数组和二维数组
本文知识点(目录): 一维数组(一维数组的概念.优点.格式.定义.初始化.遍历.常见异常.内存分析以及常见操作(找最大值.选择排序.冒泡排序等等)) 二维数组(二维数组的遍历.排序.查找.定义. ...
- 数组(Array),二维数组,三维数组
数组(Array):相同类型数据的集合就叫做数组. (一)定义数组的方法: A) type[] 变量名 = new type[数组中元素的个数] 例如: int[] a = new int[10] ; ...
- java se系列(四) 函数、数组、排序算法、二分法、二维数组
1 函数 1.1 数的概述 发现不断进行加法运算,为了提高代码的复用性,就把该功能独立封装成一段独立的小程序,当下次需要执行加法运算的时候,就可以直接调用这个段小程序即可,那么这种封装形形式的具体表 ...
- 《Java大学教程》—第16章 二维数组
多维(Multi-dimensional)数组维数由索引个数决定.常用的数组:一维(one-dimensional)数组.二维(two-dimensional)数组 16.2 创建二维数组索引从 ...
- 树状数组+二维前缀和(A.The beautiful values of the palace)--The Preliminary Contest for ICPC Asia Nanjing 2019
题意: 给你螺旋型的矩阵,告诉你那几个点有值,问你某一个矩阵区间的和是多少. 思路: 以后记住:二维前缀和sort+树状数组就行了!!!. #define IOS ios_base::sync_wit ...
- C语言中指针和数组
C语言数组与指针的那些事儿 在C语言中,要说到哪一部分最难搞,首当其冲就是指针,指针永远是个让人又爱又恨的东西,用好了可以事半功倍,用不好,就会有改不完的bug和通不完的宵.但是程序员一般都有一种迷之 ...
随机推荐
- 生产者和消费者之间的线程通讯wait()
生产者与消费者,采用notify()唤醒 package com.dwz.concurrency.chapter9; /** * 生产者和消费者之间的通信问题 * 执行wait()之后锁被释放 */ ...
- Innodb内存结构
聚集索引与非聚集索引: 聚集索引:主键,有序,存储顺序与内存一致 非聚集索引:非主键,无序 聚集索引在叶子节点存储的是表中的数据 非聚集索引在叶子节点存储的是主键和索引列 使用非聚集索引查询出数据 ...
- Windows环境安装MySQL8.0.11
网络开发数据库是必不可少的.曾经安装个Mysql,但是忘了.再次安装还是得百度.那还不如自己写篇博客记录一下呢,以后再忘记就看自己的博客好 Mysql官网安装地址(windows环境): https: ...
- 如何使用SendGrid发送邮件
特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...
- Linux编程之recvmsg和sendmsg函数
recvmsg 和 sendmsg 函数 #include <sys/types.h> #include <sys/socket.h> ssize_t send(int soc ...
- map,实现技巧,id
cf #include<iostream> #include<cstdio> #include<algorithm> #include<vector> ...
- Qt之CMake和MinGW编译OpenCV
这里编译的是最新版OpenCV3.4.3,编译过程比较曲折,大部分编译错误都可以查得到解决方法,也遇到了Google无果的错误,好在最后还是解决了,特此记录. 编译环境 win10-64bit Qt5 ...
- tensorflow中一个矩阵和一个向量相加
import tensorflow as tf x=tf.constant([[1,2],[3,4]]) y=tf.constant([[1],[1]])#列向量 z=tf.constant([1,1 ...
- nginx优化后的主配置文件
user web web; #nginx的程序账户和程序组 worker_processes auto; #worker进程数 auto设为默认 error_log /app/logs/nginx/w ...
- Samrty技术的 初步了解
<span style="font-size:18px;">Smarty 技术的使用 <?php #smarty 测试 #引入smarty require_onc ...